pandas数据处理---常用方法
pandas数据处理
前言
pandas包含两种数据类型:series和dataframe。
- series是一种一维数据结构,每一个元素都带有一个索引,与一维数组的含义相似,其中索引可以为数字或字符串。
df1 = pd.Series([1.1, 2.2, 3.3],index=['i1','i2','i3'])
- dataframe是一种二维数据结构,数据以表格形式(与excel类似)存储,有对应的行和列
df1 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3', 'K4', 'K5'],
'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
一、基本操作
1、读入、保存csv数据
(1) 读入数据 read_csv
# 以BeiJing PM2.5数据为例
import pandas as pd
file_path = 'pm25_data_2010.1.1-2014.12.31.csv'
data = pd.read_csv(file_path)
print(data)
#输出结果:原数据
No year month day hour pm2.5 ... TEMP PRES cbwd Iws Is Ir
1 2010 1 1 0 NaN ... -11.0 1021.0 0 1.79 0 0
2 2010 1 1 1 NaN ... -12.0 1020.0 0 4.92 0 0
... ... ... ... ... ... ... ... ... ... ... .. ..
43823 2014 12 31 22 8.0 ... -4.0 1034.0 0 246.72 0 0
43824 2014 12 31 23 12.0 ... -3.0 1034.0 0 249.85 0 0
[43824 rows x 12 columns]
(2)保存数据 to_csv()
new_path = 'pm_new_data.csv'
usedData.to_csv(new_path, index=False)
2、处理缺省值NaN
(1)判断是否存在NaN
print(pd.notnull(data)) # pd.isnull(data)
#输出结果: 可以看到, PM2.5该列显示False的位置存在NaN值
No year month day hour pm2.5 ... TEMP PRES cbwd Iws Is Ir
True True True True True False ... True True True True True True
True True True True True False ... True True True True True True
True True True True True False ... True True True True True True
... ... ... ... ... ... ... ... ... ... ... ... ...
True True True True True True ... True True True True True True
True True True True True True ... True True True True True True
[43824 rows x 12 columns]
(2)删除含有NaN的行 dropna
noNaN = data.dropna(how='any',axis=0)
print(noNaN)
#输出结果:对比原数据,含有NaN的1、2等行均被删除
No year month day hour pm2.5 ... TEMP PRES cbwd Iws Is Ir
25 2010 1 2 0 129.0 ... -4.0 1020.0 3 1.79 0 0
26 2010 1 2 1 148.0 ... -4.0 1020.0 3 2.68 0 0
... ... ... ... ... ... ... ... ... ... ... .. ..
43823 2014 12 31 22 8.0 ... -4.0 1034.0 0 246.72 0 0
43824 2014 12 31 23 12.0 ... -3.0 1034.0 0 249.85 0 0
[43824 rows x 12 columns]
(3)将NaN设置为指定值 fillna
meanNaN = data.fillna(value = newData.mean()['pm2.5'])
print(meanData)
#输出结果:对比原数据,NaN都被赋值为pm2.5的平均值: 98.613215
No year month day hour pm2.5 ... TEMP PRES cbwd Iws Is Ir
1 2010 1 1 0 98.613215 ... -11.0 1021.0 0 1.79 0 0
2 2010 1 1 1 98.613215 ... -12.0 1020.0 0 4.92 0 0
3 2010 1 1 2 98.613215 ... -11.0 1019.0 0 6.71 0 0
... ... ... ... ... ... ... ... ... ... ... .. ..
43823 2014 12 31 22 8.0 ... -4.0 1034.0 0 246.72 0 0
43824 2014 12 31 23 12.0 ... -3.0 1034.0 0 249.85 0 0
[43824 rows x 12 columns]
3、统计方法
(1)查看平均值 mean()
dataMean= data.mean() #计算所有列的平均值(计算时会忽略NaN
print(dataMean)
#输出结果:
No 21912.500000
year 2012.000000
month 6.523549
day 15.727820
hour 11.500000
pm2.5 98.613215
DEWP 1.817246
TEMP 12.448521
PRES 1016.447654
cbwd 1.488933
Iws 23.889140
Is 0.052734
Ir 0.194916
dtype: float64
print(dataMean["pm2.5"]) #输出指定列
#输出结果:
98.61321455085375
pmMean = data["pm2.5"].mean() #只计算pm2.5列的平均值
print(pmMean)
#输出结果:
98.61321455085375
(2)查看最大/最小值及其位置 max()、min()、argmax()、argmin()
dataMax = data.max() #查看所有列的最大值
print(dataMax)
#输出结果:
No 43824.0
year 2014.0
month 12.0
day 31.0
hour 23.0
pm2.5 994.0
DEWP 28.0
TEMP 42.0
PRES 1046.0
cbwd 3.0
Iws 585.6
Is 27.0
Ir 36.0
dtype: float64
pmMax = data["pm2.5"].max() #只计算pm2.5列的最大值
pmMaxIndex = data["pm2.5"].argmax()#取最大值位置
print(pmMax ,pmMaxIndex)
#输出结果:
994.0 18049
#min()的用法与max()的用法相同,这里不再赘述
(3)查看中位数
dataMid = newData.median()
print(dataMid )
#输出结果:
No 21912.50
year 2012.00
month 7.00
day 16.00
hour 11.50
pm2.5 72.00
DEWP 2.00
TEMP 14.00
PRES 1016.00
cbwd 1.00
Iws 5.37
Is 0.00
Ir 0.00
dtype: float64
pmMid = newData["pm2.5"].median() #查看指定列的中位数
print(pmMid)
#输出结果:
72.0
(4)获取不重复列表数据
uniqueData = newData["pm2.5"].unique()#获取不重复的列表数据
print(uniqueData)
#输出结果:
[ nan 129. 148. 159. 181. 138. 109. 105. ... ... ... ... 2. 3. 577. 483. 519. 551. 542. 580.]
4、行列操作
(1)交换列的位置
cols = list(data)
cols.pop(cols.index('No')) # pop()方法删除指定列
cols.insert(len(data),cols.pop(cols.index('pm2.5'))) # 将pm2.5插入到最后一列
newData = data.loc[:, cols]
print("pm2.5")
#输出结果:对比原数据,可以看到pm2.5现在被移动到最后一列,其他列依次前移
year month day hour DEWP TEMP PRES cbwd Iws Is Ir pm2.5
2010 1 1 0 -21 -11.0 1021.0 0 1.79 0 0 NaN
2010 1 1 1 -21 -12.0 1020.0 0 4.92 0 0 NaN
2010 1 1 2 -21 -11.0 1019.0 0 6.71 0 0 NaN
... ... ... ... ... ... ... ... ... .. .. ...
2014 12 31 21 -22 -3.0 1034.0 0 242.70 0 0 10.0
2014 12 31 22 -22 -4.0 1034.0 0 246.72 0 0 8.0
2014 12 31 23 -21 -3.0 1034.0 0 249.85 0 0 12.0
[43824 rows x 12 columns]
二、数据合并、分组、聚合
Pandas包的merge、join、concat方法可以完成数据的合并和拼接,merge方法主要基于两个dataframe的共同列进行合并,join方法主要基于两个dataframe的索引进行合并,concat方法是对series或dataframe进行行拼接或列拼接。
1、数据合并
(1)merge
pandas的merge方法是基于共同列,将两个dataframe连接起来。merge方法的主要参数:
- left/right:左/右位置的dataframe。
- how:数据合并的方式。left:基于左dataframe列的数据合并;right:基于右dataframe列的数据合并
- outer:基于列的数据外合并(取并集);inner:基于列的数据内合并(取交集);默认为’inner’。
- on:用来合并的列名,这个参数需要保证两个dataframe有相同的列名。
- left_on/right_on:左/右dataframe合并的列名,也可为索引,数组和列表。
- left_index/right_index:是否以index作为数据合并的列名,True表示是。
- sort:根据dataframe合并的keys排序,默认是。
-
suffixes:若有相同列且该列没有作为合并的列,可通过suffixes设置该列的后缀名,一般为元组和列表类型。
merges通过设置how参数选择两个dataframe的连接方式,有内连接,外连接,左连接,右连接。
内连接 inner
how=‘inner’,dataframe的链接方式为内连接,我们可以理解基于共同列的交集进行连接,参数on设置连接的共有列名
# 单列的内连接
#定义数据
df1 = pd.DataFrame({'alpha':['A','B','B','C','D','E'],'col1':[1,1,2,3,3,1],
'col2':['low','medium','medium','high','low','high']})
#定义df2
df2 = pd.DataFrame({'alpha':['A','A','B','F'],'pazham':['apple','orange','pine','pear'],
'kilo':['high','low','high','medium'],'price':np.array([5,6,5,7])})
print(df1)
print(df2)
打印的数据为:
alpha col1 col2 alpha pazham kilo price
0 A 1 low 0 A apple high 5
1 B 1 medium 1 A orange low 6
2 B 2 medium 2 B pine high 5
3 C 3 high 3 F pear medium 7
4 D 3 low
5 E 1 high
#基于共同列alpha的内连接
df3 = pd.merge(df1,df2,how='inner',on='alpha')
print(df3)
#输出结果:取共同列alpha值的交集进行连接
alpha col1 col2 pazham kilo price
0 A 1 low apple high 5
1 A 1 low orange low 6
2 B 1 medium pine high 5
3 B 2 medium pine high 5
外连接
how=‘outer’,dataframe的链接方式为外连接,我们可以理解基于共同列的并集进行连接,参数on设置连接的共有列名
df3 = pd.merge(df1,df2,how='outer',on='alpha')
print(df3)
#输出结果:若两个dataframe间除了on设置的连接列外并无相同列,则该列的值置为NaN。
alpha col1 col2 pazham kilo price
0 A 1.0 low apple high 5.0
1 A 1.0 low orange low 6.0
2 B 1.0 medium pine high 5.0
3 B 2.0 medium pine high 5.0
4 C 3.0 high NaN NaN NaN
5 D 3.0 low NaN NaN NaN
6 E 1.0 high NaN NaN NaN
7 F NaN NaN pear medium 7.0
左连接
how=‘left’,dataframe的链接方式为左连接,我们可以理解基于左边位置dataframe的列进行连接,参数on设置连接的共有列名。
df3 = pd.merge(df1,df2,how='left',on='alpha')
print(df3)
输出结果:
alpha col1 col2 pazham kilo price
0 A 1 low apple high 5.0
1 A 1 low orange low 6.0
2 B 1 medium pine high 5.0
3 B 2 medium pine high 5.0
4 C 3 high NaN NaN NaN
5 D 3 low NaN NaN NaN
6 E 1 high NaN NaN NaN
因为df2的连接列alpha有两个'A'值,所以左连接的df5有两个'A'值,若两个dataframe间除了on设置的连接列外并无相同列,则该列的值置为NaN。
右连接
how=‘right’,dataframe的链接方式为左连接,我们可以理解基于右边位置dataframe的列进行连接,参数on设置连接的共有列名。
df3 = pd.merge(df1,df2,how='right',on='alpha')
print(df3)
#输出结果:
alpha col1 col2 pazham kilo price
0 A 1.0 low apple high 5
1 A 1.0 low orange low 6
2 B 1.0 medium pine high 5
3 B 2.0 medium pine high 5
4 F NaN NaN pear medium 7
基于多列的连接算法
多列连接的算法与单列连接一致,可自己编码或者图解方式去理解外连接和左连接。
前提是:要做连接的表有多个共同列
#与单列用法一样,不再详细说明
# 基于共同列column1和column2的右连接
df3 = pd.merge(df1,df2,on=['column1','column2'],how='right')
基于index的连接方法
# 基于df1的beta列和df2的index连接
df3 = pd.merge(df1,df2,how='inner',left_on='beta',right_index=True,suffixes=('_df1','_df2'))
#输出结果:
alpha_df1 col1 col2 alpha_df2 pazham kilo price
0 A 1 low A orange low 6
1 B 1 medium A orange low 6
5 E 1 high A orange low 6
2 B 2 medium B pine high 5
3 C 3 high F pear medium 7
4 D 3 low F pear medium 7
(2)Join
Join方法:基于index连接dataframe,merge方法是基于column连接,连接方法有内连接,外连接,左连接和右连接,默认情况下它是把行索引相同的数据合并在一起,
# 自定义两个数据:
A= pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3', 'K4', 'K5'],
'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
B= pd.DataFrame({'key': ['K0', 'K1', 'K2'],
'B': ['B0', 'B1', 'B2']})
print(A,B)
#输出结果:
key A key B
0 K0 A0 0 K0 B0
1 K1 A1 1 K1 B1
2 K2 A2 2 K2 B2
3 K3 A3
4 K4 A4
5 K5 A5
内连接
# lsuffix和rsuffix设置连接的后缀名 #在这个数据上,右连接结果与内连接一样(由数据决定)
afterJoin = A.join(B,lsuffix='_A', rsuffix='_B',how='inner')
afterJoin = A.join(B, lsuffix='_A', rsuffix='_B', how='right')
print(afterJoin)
#输出结果:可以看出只合并两数据*同的key
key_A A key_B B
0 K0 A0 K0 B0
1 K1 A1 K1 B1
2 K2 A2 K2 B2
基于key列进行连接 set_index()
A.set_index('key').join(B.set_index('key'),how='inner')
#输出结果:
A B
key
K0 A0 B0
K1 A1 B1
K2 A2 B2
全连接
#在这个数据上,全连接的结果与左连接一样
afterJoin = A.join(B, lsuffix='_A', rsuffix='_B', how='left')
afterJoin = A.join(B, lsuffix='_A', rsuffix='_B', how='outer')
print(afterJoin)
#输出结果:
key_A A key_B B
0 K0 A0 K0 B0
1 K1 A1 K1 B1
2 K2 A2 K2 B2
3 K3 A3 NaN NaN
4 K4 A4 NaN NaN
5 K5 A5 NaN NaN
2、数据拼接 concat()
concat方法是拼接函数,有行拼接和列拼接,默认是行拼接,拼接方法默认是外拼接(并集),拼接的对象是pandas数据类型。
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
keys=None, levels=None, names=None, verify_integrity=False,
copy=True)
参数含义
- objs:Series,DataFrame或Panel对象的序列或映射。如果传递了dict,则排序的键将用作键参数,除非它被传递,在这种情况下,将选择值(见下文)。任何无对象将被静默删除,除非它们都是无,在这种情况下将引发一个ValueError。
- axis:{0,1,…},默认为0。沿着连接的轴。
- join:{‘inner’,‘outer’},默认为“outer”。如何处理其他轴上的索引。outer为联合和inner为交集。
- ignore_index:boolean,default False。如果为True,请不要使用并置轴上的索引值。结果轴将被标记为0,…,n-1。如果要连接其中并置轴没有有意义的索引信息的对象,这将非常有用。注意,其他轴上的索引值在连接中仍然受到尊重。
- join_axes:Index对象列表。用于其他n-1轴的特定索引,而不是执行内部/外部设置逻辑。新版本pandas已经删除了join_axes,所以习惯了两个dataframe按照同一列合并的话,可以改用merge:
- keys:序列,默认值无。使用传递的键作为最外层构建层次索引。如果为多索引,应该使用元组。
- levels:序列列表,默认值无。用于构建MultiIndex的特定级别(唯一值)。否则,它们将从键推断。
- names:list,default无。结果层次索引中的级别的名称。
- verify_integrity:boolean,default False。检查新连接的轴是否包含重复项。这相对于实际的数据串联可能是非常昂贵的。
- copy:boolean,default True。如果为False,请勿不必要地复制数据。
(1) series类型的拼接方法
df1 = pd.Series([1.1, 2.2, 3.3],index=['i1','i2','i3'])
df2 = pd.Series([4.4, 5.5, 6.6],index=['i2','i3','i4'])
#数据结构为:
i1 1.1 i2 4.4
i2 2.2 i3 5.5
i3 3.3 i4 6.6
dtype: float64 dtype: float64
# 对行拼接分组
pd.concat([df1,df2],keys=['fea1','fea2'])
#行拼接若有相同的索引,为了区分索引,可以在最外层定义了索引的分组情况,若没有可以不设置keys属性
#结果为:
fea1 i1 1.1
i2 2.2
i3 3.3
fea2 i2 4.4
i3 5.5
i4 6.6
dtype: float64
列拼接
列拼接默认以并集的方式拼接
pd.concat([df1,df2],axis=1)
#输出结果:
0 1
i1 1.1 NaN
i2 2.2 4.4
i3 3.3 5.5
i4 NaN 6.6
列拼接的内连接(交集)
pd.concat([df1,df2],axis=1,join='inner')
#输出结果:
0 1
i2 2.2 4.4
i3 3.3 5.5
# 设置列名
pd.concat([df1,df2],axis=1,join='inner',keys=['fea1','fea2'])
#输出结果:
fea1 fea2
i2 2.2 4.4
i3 3.3 5.5
(2) dataframe类型的拼接方法
#定义dataframe类型的数据
df1 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3', 'K4', 'K5'],
'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
df2 = pd.DataFrame({'key': ['K0', 'K1', 'K2'],
'B': ['B0', 'B1', 'B2']})
print(df1)
print(df2)
#打印数据:
key A key B
0 K0 A0 0 K0 B0
1 K1 A1 1 K1 B1
2 K2 A2 2 K2 B2
3 K3 A3
4 K4 A4
5 K5 A5
#行拼接
df3 = pd.concat([df1,df2])
print(df3)
#输出结果:
key A B
0 K0 A0 NaN
1 K1 A1 NaN
2 K2 A2 NaN
3 K3 A3 NaN
4 K4 A4 NaN
5 K5 A5 NaN
0 K0 NaN B0
1 K1 NaN B1
2 K2 NaN B2
#若列名均不相同:
key1 A key2 B
0 K0 A0 NaN NaN
1 K1 A1 NaN NaN
2 K2 A2 NaN NaN
3 K3 A3 NaN NaN
4 K4 A4 NaN NaN
5 K5 A5 NaN NaN
0 NaN NaN K0 B0
1 NaN NaN K1 B1
2 NaN NaN K2 B2
# 列拼接
pd.concat([df1,df2],axis=1)
#输出结果:
key A key B
0 K0 A0 K0 B0
1 K1 A1 K1 B1
2 K2 A2 K2 B2
3 K3 A3 NaN NaN
4 K4 A4 NaN NaN
5 K5 A5 NaN NaN
df3 = pd.concat([df1,df2],axis=1,verify_integrity = True)
# 设置verify_integrity = True;若列拼接或行拼接有重复的列名和行名,则报错
3、数据分组与聚合
(1)分组 — groupby
对数据集进行分组,然后对每组进行统计分析
SQL能够对数据进行过滤,分组聚合
pandas能利用groupby进行更加复杂的分组运算
分组运算过程:split->apply->combine
1、拆分:进行分组的根据
2、应用:每个分组运行的计算规则
3、合并:把每个分组的计算结果合并起来
DataFrame.groupby(key, as_index=False)
GroupBy对象:DataFrameGroupBy,SeriesGroupBy
key:分组的列数据,可以多个
groupby()进行分组,GroupBy对象没有进行实际运算,只是包含分组的中间数据
单列分组
#以pm2.5数据为例
data = pd.read_csv( 'pm25_data_2010.1.1-2014.12.31.csv')
#No year month day hour pm2.5 ... TEMP PRES cbwd Iws Is Ir
#先分组再取列 ,按照列名分组
newData = data.groupby(['month'])['pm2.5'].count()
#count():统计该组元素的个数
#先取列,再分组
newData = data['pm2.5'].groupby(data['month']).count() #一样的结果
print(newData)
#输出结果: 按照month分组,计算pm2.5的统计信息
month
1 3471
2 3373
3 3556
4 3405
5 3609
6 3405
7 3647
8 3337
9 3333
10 3579
11 3501
12 3541
Name: pm2.5, dtype: int64
#不作为索引
newData = data.groupby(['month'],as_index=False)['pm2.5'].count()
print(newData)
#输出结果:
month pm2.5
0 1 3471
1 2 3373
2 3 3556
3 4 3405
4 5 3609
5 6 3405
6 7 3647
7 8 3337
8 9 3333
9 10 3579
10 11 3501
11 12 3541
多列分组
grouped2 = data.groupby(['year', 'cbwd']).count()
print(grouped2)
输出结果:
year cbwd
2010 0 2887
... ...
2011 0 2900
... ...
2012 0 2581
... ...
2013 0 2690
... ...
2014 0 2426
... ...
3 3186
Name: pm2.5, dtype: int64
# GroupBy对象转换list
print(list(grouped2))
输出结果:
[2887, 1545, 899, 2760, 2900, 1628, 832, 2672, 2581, 1799, 985, 2930, 2690, 1916, 1047, 3025, 2426, 2056, 993, 3186]
按照数值类型dtypes分组
newData = data.groupby(data.dtypes, axis=1).size()
print(newData )
#输出结果:
int64 9
float64 4
dtype: int64
(2)聚合 — aggregation
数组产生标量的过程,如mean()、count()等;常用于对分组后的数据进行计算
内置的聚合函数:sum(), mean(), max(), min(), count(), size(), describe(),std(), var()
函数名 | 说明 |
---|---|
count | 分组中非NaN的值的数量 |
sum | 非NaN值的和 |
mean | 非NaN值的平均值 |
median | 非NaN值的算术中位数 |
std、var | 无偏(分母为n-1) 标准差、方差 |
min、max | 非NaN值的最小值、最大值 |
prod | 非NaN值的乘积 |
first、last | 第一个、最后一个非NaN值 |
本文地址:https://blog.csdn.net/weixin_43165676/article/details/110468256