前言:pandas主要分为两大块,Series和datafram,下面对这两块分别进行总结。其次,在看该篇文章时候,需有一点numpy的知识,后面我都会将其类型转换的numpy的数据类型进行处理。
data = pd.Series(np.arange(10))
dd = pd.Series([1,2,3,4],index=list('abcf')) #还可以指定索引
#推导式创建一个字典
a = { string.ascii_uppercase[i]:i for i in np.arange(10)}
# 装换成Seriers
data = pd.Series(a)
结果:
注意:Seriers中,index的数量必须和值的个数一样多,但是可以此时给的index可以和之前的一样,也可以不一样,此时,不一样的将以nan填充。
eg:
这里data[[1,2,3]]和data[[‘F’,‘G’,‘H’]]等价,应为通过1,2,3也可以唯一的确定数据。这里的1,2,3表示坐标。
这里特别注意,若索引也为数值的话,当在使用data[[1,2,3]]这种写法时候,这里的1,2,3不在表示坐标,而是表示键
可以看到这里的2,3,4不是去的第2,3,4坐标的位置的值,而是取的对应键的值。
获取index:
s = data.index ##这里获取的s的类型为RangeIndex,可以将其装换位ndarray类型
s = s.to_numpy() ##转化为numpy类型
获取value:
s = data.values #这里获取的类型直接就位ndarray类型
data[:]=[要修改的值]
data = pd.read_csv("./c.csv") #这里读出来的数据类型为DataFrame
在读取csv文件的时候我们可以指定一些参数。
index_col=1 #指定以那一列作为行索引,这里1表示以第1列作为索引
#不指定会默认生成以0开头的index作为索引。
encoding='gbk' #指定以什么编码格式解析数据,这里以gbk
看一下data:
上面DataFrame和上面为dataFrame总的列索,用columns表示。最左边为行索引,用index表示。
data = pd.DataFrame(np.arange(12).reshape(3,4)) #创建一个3行4列的dataFrame
DataFrame对象既有行索引,也有列索引:
行索引:表明不同行,横向索引,叫index,0轴,axis=0
列索引:表明不同列,纵向索引,叫columns,1轴,axis= 1
注意:通过列表创建时如果是二维的。那么创建的dataframe就和原list的格式一样,但若是一维数,那么它每个数等价为一维数据。如下所示。
二维:
data = pd.DataFrame([[1,2,3],[4,5,6]])
data
data = pd.DataFrame([1,2,3])
data
d1 = {'name':['xiaoming','xiaohong'],'age':[20,21]}
df = pd.DataFrame(d1)
df
d1 = [{'name':'xiaohong','age':'32'},{'name':"xiaohong",'tel':10086}]
df = pd.DataFrame(d1)
df
data.reset_index(inplace=True) #该方法会将索引列提出来,并重新生成新的以0开始编号的index.如果不想将索引列提出来,可以使用drop参数,设置为False即可
data.rename({'b':'first'},axis=1,inplace=True) #修改columns某个值为另一个值
data.rename({0:'修改'},axis=0,inplace=True) #修改index某个值为另一个值
直接写入要插入的columns值即可:
data["插入"]=np.nan
通过列表字典形式插入:
data = data.append([{"first":8,'a':99}],ignore_index=True)
#其中ignore_index为True会让索引重新从0开始编号,为False为添加索引号为0,不建议这样使用。
dd = pd.Series([1,2,3,4],index=list('abcf'))
res1 = res.append(dd,ignore_index=True)
在通过Series插入的时候实质和字典一样,都会进行columns查询,若又则对应位置插入,若没有,则创建新的一列,上一个表没有该数据则填为nan.
data1.join(data2) #会将行标签相同的放在一起,若data1的标签大于data2个数,则data2中在data1没有的标签行会以nan显示,若data1的小于data2的index数量,那么data2多余的index将会被截掉。
data2多于data1的index
data1少于data1的index
通过append方法进行合并:
res = pd.DataFrame() #这种方法可以进行迭代,在合并的时候会自动检查columns,若上一个表不存在会创建一个columns,上一个表因为没有该columns,值会默认全为nan
res = res.append(data,ignore_index=True)
res = res.append(data1,ignore_index=True)
使用merge进行合并,会指定一个on参数,该参数指定以某一列的键值进行合并,如果两边根据同一键进行合并时,出现了不同的其他columns,那么会生成一个x_XX,和一个y_XX.
eg:有两组数据:
res:
data:
通过b这一列进行合并:
res.merge(data,on="b")
上述结果解析:因为通过b这一列键进行合并的,在res中,b这一列数据有两列为1,而data中有一列为1,因此,res中这两列1将会和data中这一列进行匹配,因此res就会将1这两列拿出来,然后将data中这一列拿出来,然后res中取出来的每一行和data中取出来的这一行进行合并,因此合并完之后总共的数据就是两列,这里因为res和data中都有a,因此为了避免数据的冲突,这里会自动生成x_a.y_a.
合并参数how指定
在进行合并的时候,如果不指定how参数,那么默认会是inner方式,就是去交集,如上面的合并。另外还可以指定outer,即以并集的方式进行合并:
eg:
data:
res:
data.merge(res,on="b",how='outer')
左连接以左边数据为准,然后去找右边数据,如果有,则进行合并,如果没有,就进行舍弃:
eg:
data:
res:
左连接:
data.merge(res,on="b",how='left')
同理,右链接将以右边数据为准:
eg:
data:
res:
右连接:
data.merge(res,on="b",how='right')
df.drop(['age'],axis=1) #['age']代表选中age这一列,也可以使用labels属性
#等价于df.drop(axis=1,labels='age')
d1 = [{'name':'xiaohong','age':'32'},{'name':"xiaohong",'tel':10086}]
df = pd.DataFrame(d1)
df.drop([0],axis=0,inplace=True) # [0]表示选中这一行,也可以使用labels,等价于labels='0'
df.reset_index(drop=True,inplace=True)
df
注意,这里删除某一列之后要记得进行重设索引,还有这里要记得使用drop参数,否者会在原数据中新增加一列。
df.shape #行数 列数
df.dtypes # 列数据类型
df.ndim # 数据维度
df.index # 行索引
df.columns # 列索引
df.values #对象值,二维的ndarray
df['某列属性'].unique() # 取唯一的值,只有Series含有该方法
df.head(5) # 显示前5行
df.tail(5) #显示后5行
df.info() # 显示数据信息,可以查是否为空,那一列有数据缺失
df.describe() # std:标准差。mean:均值,min:最小值,25%:1/4中位数,50%:中位数,75%:3/4中位数,max:最大值
res.sort_values(by='a',ascending=False,inplace=True)
res
ascending参数是定是否升序。
在dataFrame数据结构中我们也可以进行切片,而且切片还可以通过指定infdex的名字进行(index不是数值型)
通过当前位置进行切片:
res[1:6:2] #1表示起始,6表示终止,2表示步长。
res['a':'f':1]
首先说一下loc和iloc的区别,后面就直接使用loc进行演练,因为我比较喜欢使用loc,而且用起来也比较顺手。大家可以根据自己的喜好自由选择。
语法:
loc[行索引,列索引] #
loc和iloc其实在使用上区别不大,唯一的区别就在于loc是通过标签进行索引的,而iloc是通过位置进行索引的。举个例子:
如上数据:
我们可以使用loc使用标签(abcd)这些标签进行索引,但是就不能使用位置进行索引了。
res.loc['a':'f',:] #正确,loc通过标签进行索引
res.loc[1:4,:] # 错误,loc只能通过标签进行
res.iloc['a':'f',:] #错误,iloc只能通过位置进行索引
res.iloc[1:4,:] #正确,iloc通过位置进行索引
以上就是loc和iloc的区别,下面将以loc进行用法讲解,iloc其实也试用,只需要将对应的标签换成位置坐标即可。
不适用loc函数的时候,方括号写数组表示取行,方括号写字符串,表示取列,但是在使用loc函数的时候,方括号不管是写数组还是写字符串,都表示取行,这是因为在使用loc函数的时候,如果只写一个参数,他会默认是逗号后面为空,也就是所有列,这样看来,就是取该行的所有列。
eg:
针对数据:
res[:'a'] #是取行
res['a'] #是取列
res.loc['a'] #表示取行
res.loc[['a','s']]
res.loc[['a','s'],'d']
cat() 拼接字符串,在使用此方法时必须保证所操作的该列为str类型,否则会报 Can only use .str accessor with string values!的错误!
因此在使用cat函数时,可以先试用astype进行转一下:
res['e'] = res['e'].astype(np.str)
res.loc[:,'e'] = res.loc[:,'e'].str.cat(['1','2','3','4','5','6','70'],sep='|')
# sep表示使用什么作为分隔符
res.loc[:,'d'] = res.loc[:,'d'].str.split('|') #在使用之前也需要保证操作列为str类型
res['d'].str.get(1)
res['e'] = res['e'].str.join('|')
res['d'].str.contains("4")
res['e'] = res['e'].str.replace('|','_')
res['e'] = res['e'].str.wrap(2)
pd.isnull(res)
res[pd.isnull(res['a'])]
res.dropna(axis=0,how='any') #只要含有nan就删除这一行或这一列,删除行还是列,有axis指定。how若为any表示只要已出现nan就删除该行或该列,all表示该行该列全部为nan才进行删除
在填充数据之前先来看几个重要的数:
res.describe():
其中的数据都是跳过nan进行统计的。
第二种方式获取均值
res['a'].mean() #通过mean方法进行获取
res.fillna(axis=0,method='ffill') #指定轴 使用前一个填充nan
# ffill使用前一个填充,bfill使用后一个填充
res.fillna(axis =0,value=0) #使用指定值填充
res['a'] = res['a'].fillna(value=res['a'].mean())
对于异常0,我们通常把它变为nan,因为变成nan之后,在使用diecribe和mean等方法是,就不会统计该项,非常方便。
res[res==0]=np.nan
groupby:返回的是一个可迭代对象:内置了许多可用的方法.
dd = data.groupby(by='订单号').sum() #sum函数统计每个分组每项数据的和,如果遇到字符串,则自动忽略该项。
# 返回的是一个DataFrame
dd = data.groupby(by='订单号').count() #count统计分组之后每组的个数,会自动忽略nan
dd = data.groupby(by='订单号').mean() #统计每个分组的均值
dd = data.groupby(by='订单号').describe() #统计每个分组的描述信息,包括最大值,最小值,均值、方差等
for i in data.groupby(by='订单号'):
print(type(i))
break
返回是一个元组:
("分组的组名",该组名对应的数据,为DataFrame格式)
pd.date_range(start=None,end=None,periods=None,freq='D')
# start表示起始时间
# end 表示结束时间
# period 表示 时间段,一共的个数,常常和start配合使用,而不和end在一起使用。
生成一个时间序列:
pd.date_range(start='2020-3-1',end='2021-4-4',freq='D') #在这里start可以写"20200301"
#或2020-3-1“”或“2020-03-01”都是可以识别的。
比如我们现在有这样一组时间序列:
data:
我们要将其date转换成pandas中标准的datetime64类型,我们可以调用to_datetime函数,并指定其格式化的方式:
data1['date'] = pd.to_datetime(data1['date'],format="%Y年%m月%d号")
#to_datetime功能及其强大,还可以直接将一个时间戳转化为标准date格式
data1['date'] = pd.to_datetime(data1['date'],unit='ms',origin=pd.Timestamp('1970-01-01 00:00:00'))
#unit 表示时间戳的单位
#origin 表示起始时间
重采样:指的是将时间序列从一个频率转化为另一个频率进行处理的过程,将高频率数据转化为低频率数据为降采样,低频率转化为高频率为升采样。
假设现在有一组这样的数据:
以采样值作为当前前,不进行累计求和。
hh = data.resample("3D").asfreq()#3D表示以每三天进行采样
hh = data.resample("3D").count()
hh = data.resample("3D").sum()
hh = data.resample("3D").mean()
hh = data.resample("0.5D").asfreq() #以每半天进行采样