Pandas学习笔记
链接:https://www.bilibili.com/video/BV1tA411H7cQ?p=1
官方文档:https://pandas.pydata.org/docs/user_guide/index.html#user-guide
Pandas文件操作
函数 | 说明 |
---|---|
read_csv | 从文件、URL、文件型对象中加载带分隔符的数据,默认分隔符为逗号 |
read_excel | 从Excel XLS或XLSX file读取表格数据 |
read_json | 读取JSON字符串中的数据 |
CSV读取文件
a.csv:
read_csv(file_path or buf,usecols,encoding…):
file_path:文件路径,
header:用作列名的行号。默认为0(第一行),如果没有header行就应该设置为None
index_col:用作行索引的列编号或列名。可以是单个名称/数字或由多个名称、数字组成的列表
usecols:指定读取的列名,
na_values:一组用于替换NA的值
nrows:需要读取的行数
skiprows:需要忽略的行数(从文件开始处算起),或需要跳过的行号列表(从0开始)
converters:由列号/列名跟函数之间的映射关系组成的字典。如{‘foo’:f}会对foo列的所有值应用函数f
encoding:编码,通常为’utf-8’。
data=pd.read_csv(
'a.csv',
header=0,
index_col=0,
na_values={'age':0},
nrows=4,
encoding='gb18030'
)
print(data)
# age 语文 数学
# Score
# A 15.0 80 99
# B 16.0 90 95
# C NaN 89 90
# D 14.0 87 89
CSV写入文件
to_csv(file_path or buf,sep,columns,header,index,na_rep,mode…):
file_path:保存文件路径,默认None,
sep:分隔符,默认’,’ ,
columns:是否保留某列数据,默认None,
header:是否保留列名,默认True,
index:是否保留行索引,默认True,
na_rep:指定字符串来代替空值,默认是空字符,
mode:默认’w’,追加’a’
data['总分'] = data.iloc[:, 1:3].sum(axis=1)
mean_age=data.iloc[:,0].mean()
data.to_csv('a.csv',na_rep=mean_age,encoding='gb18030')
Pandas数据清洗
处理缺失数据
- 删除含有空值的行或列:dropna
DataFrame.dropna(axis=0, how=‘any’, thresh=None, subset=None, inplace=False)
axis:维度,axis=0表示index行,axis=1表示columns列,默认为0
how:"all"表示这一行或列中的元素全部缺失(为nan)才删除这一行或列,"any"表示这一行或列中只要有元素缺失,就删除这一行或列
thresh:一行或一列中至少出现了thresh个才删除。
subset:在某些列的子集中选择出现了缺失值的列删除,不在子集中的含有缺失值得列或行不会删除(有axis决定是行还是列)
inplace:是否直接在原数据上进行修改。
- 填充缺失值:fillna
DataFrame.fillna(value=None, method=None, axis=None, limit=None inplace=False)
value:需要用什么值去填充缺失值,不同的列用不同的值填充时可使用字典
axis:确定填充维度,从行开始或是从列开始
method:ffill:用缺失值前面的一个值代替缺失值;backfill/bfill,缺失值后面的一个值代替前面的缺失值。注意这个参数不能与value同时出现
limit:确定填充的个数,如果limit=2,则只填充两个缺失值。
inplace:是否直接在原数据上进行修改。
数据转换
处理重复数据
drop_duplicates()过滤重复行
- 默认判断全部列,可指定按某些列判断
df_obj = pd.DataFrame({'A': ['a'] * 4 + ['b'] * 4, 'B': np.random.randint(0, 4, 8)})
print(df_obj)
# A B
# 0 a 3
# 1 a 2
# 2 a 3
# 3 a 1
# 4 b 2
# 5 b 0
# 6 b 3
# 7 b 2
df_obj.drop_duplicates('B',inplace=True)
print(df_obj)
# A B
# 0 a 3
# 1 a 2
# 3 a 1
# 5 b 0
利用函数或映射进行数据转换
- map
map()是Series对象的一个函数,DataFrame中没有map(),map()的功能是将一个自定义函数作用于Series对象的每个元素。
DataFrame对象的一行或者一列可以看成一个Series对象,因此也适用map()函数 - apply
apply()函数的功能是将一个自定义函数作用于DataFrame的行或者列 - applymap()函数的功能是将自定义函数作用于DataFrame的所有元素
df = pd.DataFrame({'key':list('abcd'),'data1': np.arange(4),'data2': np.arange(5, 9)})
print(df)
# key data1 data2
# 0 a 0 5
# 1 b 1 6
# 2 c 2 7
# 3 d 3 8
df['total'] = df[['data1','data2']].apply(lambda x : x.sum(), axis = 1)
print(df)
# key data1 data2 total
# 0 a 0 5 5
# 1 b 1 6 7
# 2 c 2 7 9
# 3 d 3 8 11
替换值
replace根据值的内容进行替换
# 单个值替换单个值
print(df_obj.replace(1, -100))
# 多个值替换一个值
print(df_obj.replace([6, 8], -100))
# 多个值替换多个值
print(df_obj.replace([4, 7], [-100, -200]))
字符串操作
字符串方法
ser_obj.str.function(parameters)
方法 | 说明 |
---|---|
lower() | 将Series/Index中的字符串转换为小写。 |
upper() | 将Series/Index中的字符串转换为大写。 |
len() | 计算字符串长度。 |
strip() | 帮助从两侧的系列/索引中的每个字符串中删除空格(包括换行符)。 |
split(’ ') | 用给定的模式拆分每个字符串。 |
cat(sep=’ ') | 使用给定的分隔符连接系列/索引元素。 |
get_dummies() | 返回具有单热编码值的数据帧(DataFrame)。 |
contains(pattern) | 如果元素中包含子字符串,则返回每个元素的布尔值True,否则为False。 |
replace(a,b) | 将值a替换为值b。 |
repeat(value) | 重复每个元素指定的次数。 |
count(pattern) | 返回模式中每个元素的出现总数。 |
startswith(pattern) | 如果系列/索引中的元素以模式开始,则返回true。 |
endswith(pattern) | 如果系列/索引中的元素以模式结束,则返回true。 |
find(pattern) | 返回模式第一次出现的位置。 |
findall(pattern) | 返回模式的所有出现的列表。 |
swapcase | 变换字母大小写。 |
islower() | 检查系列/索引中每个字符串中的所有字符是否小写,返回布尔值 |
isupper() | 检查系列/索引中每个字符串中的所有字符是否大写,返回布尔值 |
isnumeric() | 检查系列/索引中每个字符串中的所有字符是否为数字,返回布尔值。 |
数据合并
数据合并(pd.merge)
根据单个或多个键将不同DataFrame的行连接起来
pd.merge:(left, right, how=‘inner’,on=None,left_on=None, right_on=None )
left:合并时左边的DataFrame
right:合并时右边的DataFrame
how:合并的方式,默认’inner’, ‘outer’, ‘left’, ‘right’
on:需要合并的列名,必须两边都有的列名,并以 left 和 right 中的列名的交集作为连接键
left_on:left Dataframe中用作连接键的列
right_on:right Dataframe中用作连接键的列
- 内连接 inner:对两张表的键的交集进行联合
- 全连接 outer:对两者表的键的并集进行联合
- 左连接 left:对所有左表的键进行联合
- 右连接 right:对所有右表的键进行联合
left=pd.DataFrame({'key':['k0','k1','k2','k3'],
'A':['a0','a1','a2','a3'],
'B':['b0','b1','b2','b3']})
right=pd.DataFrame({'key':['k0','k1','k2','k3'],
'C':['c0','c1','c2','c3'],
'D':['d0','d1','d2','d3']})
df=pd.merge(left,right,on='key')
print(df)
# key A B C D
# 0 k0 a0 b0 c0 d0
# 1 k1 a1 b1 c1 d1
# 2 k2 a2 b2 c2 d2
# 3 k3 a3 b3 c3 d3
指定多个键,进行合并
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
df=pd.merge(left,right,on=['key1','key2'])
print(df)
# key1 key2 A B C D
# 0 K0 K0 A0 B0 C0 D0
# 1 K1 K0 A2 B2 C1 D1
# 2 K1 K0 A2 B2 C2 D2
指定左连接,以左边的键去匹配右边的
df=pd.merge(left, right, how='left', on=['key1', 'key2'])
print(df)
# key1 key2 A B C D
# 0 K0 K0 A0 B0 C0 D0
# 1 K0 K1 A1 B1 NaN NaN
# 2 K1 K0 A2 B2 C1 D1
# 3 K1 K0 A2 B2 C2 D2
# 4 K2 K1 A3 B3 NaN NaN
指定全连接,结果中的键是并集
df=pd.merge(left, right, how='outer', on=['key1', 'key2'])
print(df)
# key1 key2 A B C D
# 0 K0 K0 A0 B0 C0 D0
# 1 K0 K1 A1 B1 NaN NaN
# 2 K1 K0 A2 B2 C1 D1
# 3 K1 K0 A2 B2 C2 D2
# 4 K2 K1 A3 B3 NaN NaN
# 5 K2 K0 NaN NaN C3 D3
处理重复列名
参数suffixes:默认为(’_x’,’_y’)
df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data' : np.random.randint(0,10,7)})
df_obj2 = pd.DataFrame({'key': ['a', 'b', 'd'],
'data' : np.random.randint(0,10,3)})
print(pd.merge(df_obj1, df_obj2, on='key', suffixes=('_left', '_right')))
# key data_left data_right
# 0 b 4 1
# 1 b 4 1
# 2 b 2 1
# 3 a 1 4
# 4 a 6 4
# 5 a 0 4
按索引连接
参数left_index=True或right_index=True
df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1' : np.arange(0,7)})
df_obj2 = pd.DataFrame({'data2' : list('abc')}, index=['a', 'b', 'd'])
print(df_obj1)
# key data1
# 0 b 0
# 1 b 1
# 2 a 2
# 3 c 3
# 4 a 4
# 5 a 5
# 6 b 6
print(df_obj2)
# data2
# a a
# b b
# d c
print(pd.merge(df_obj1, df_obj2, left_on='key', right_index=True))
# key data1 data2
# 0 b 0 b
# 1 b 1 b
# 6 b 6 b
# 2 a 2 a
# 4 a 4 a
# 5 a 5 a
数据合并(pd.concat)
- 注意指定轴方向,默认axis=0
- join指定合并方式,默认为outer
- Series合并时查看行索引有无重复
df1 = pd.DataFrame(np.arange(6).reshape(3, 2), index=list('abc'), columns=['A', 'B'])
df2 = pd.DataFrame(np.arange(4).reshape(2, 2) + 5, index=list('ac'), columns=['C', 'D'])
print(pd.concat([df1, df2])) # 默认外连接,axis=0
# A B C D
# a 0.0 1.0 NaN NaN
# b 2.0 3.0 NaN NaN
# c 4.0 5.0 NaN NaN
# a NaN NaN 5.0 6.0
# c NaN NaN 7.0 8.0
print(pd.concat([df1, df2], axis='columns')) # 指定axis=1连接
# A B C D
# a 0 1 5.0 6.0
# b 2 3 NaN NaN
# c 4 5 7.0 8.0
# 同样我们也可以指定连接的方式为inner
print(pd.concat([df1, df2], axis=1, join='inner'))
# A B C D
# a 0 1 5 6
# c 4 5 7 8
重塑
stack
将列索引旋转为行索引,完成层级索引
DataFrame->Series
df_obj = pd.DataFrame(np.random.randint(0,10, (5,2)), columns=['data1', 'data2'])
print(df_obj)
# data1 data2
# 0 5 8
# 1 3 8
# 2 6 7
# 3 1 6
# 4 5 0
stacked = df_obj.stack()
print(stacked)
# 0 data1 5
# data2 8
# 1 data1 3
# data2 8
# 2 data1 6
# data2 7
# 3 data1 1
# data2 6
# 4 data1 5
# data2 0
# dtype: int32
unstack
将层级索引展开
Series->DataFrame
默认操作内层索引,即level=-1
# 默认操作内层索引
print(stacked.unstack())
# data1 data2
# 0 0 1
# 1 0 2
# 2 1 8
# 3 8 8
# 4 2 3
# 通过level指定操作索引的级别
print(stacked.unstack(level=0))
# 0 1 2 3 4
# data1 0 0 1 8 2
# data2 1 2 8 8 3
数据聚合与分组
分组
groupby:(by=None,as_index=True)
by:根据什么进行分组,用于确定groupby的组
as_index:对于聚合输出,返回以组便签为索引的对象,仅对DataFrame
df1 = pd.DataFrame({'key1':['A','B','C','A','B'],
'key2':['a','b','b','c','c'],
'num':[8,6,5,7,6]})
for name, group in df1.groupby('key1'):
print(name) #输出组名
print(group) # 输出数据块
print("*" * 15)
# A
# key1 key2 num
# 0 A a 8
# 3 A c 7
# ***************
# B
# key1 key2 num
# 1 B b 6
# 4 B c 6
# ***************
# C
# key1 key2 num
# 2 C b 5
# ***************
print(dict(list(df1.groupby('key1')))['A']) #取出A组的数据块
# key1 key2 num
# 0 A a 8
# 3 A c 7
根据字典分组
df = pd.DataFrame(np.random.randint(10, size=(3, 5)),
columns=['a', 'b', 'c', 'd', 'e'],
index=['x', 'y', 'z'])
m = {'a': 'one', 'b': 'one', 'c': 'two', 'd': 'one', 'e': 'two'}
print(df.groupby(m, axis=1).sum())
# one two
# x 19 10
# y 13 10
# z 18 9
根据Series分组
s = pd.Series(m)
print(df.groupby(s, axis=1).count())
# one two
# x 3 2
# y 3 2
# z 3 2
根据函数分组
df = pd.DataFrame(np.random.randint(10, size=(3, 5)),
columns=['a', 'b', 'c', 'd', 'e'],
index=['x', 'y', 'zz'])
print(df.groupby(len, axis=0).sum())
# a b c d e
# 1 6 7 7 7 1
# 2 5 0 0 4 4
聚合
函数名 | 描述 |
---|---|
count | 分组中非NA值的数量 |
sum | 非NA值的和 |
mean | 非NA值的平均值 |
median | 非NA值的中位数 |
std, var | 标准差和方差 |
min, max | 非NA的最小值,最大值 |
prod | 非NA值的乘积 |
first, last | 非NA值的第一个,最后一个 |
#根据fruit来求price的平均值
print(df1['num'].groupby(df1['key1']).mean())
# key1
# A 7.5
# B 6.0
# C 5.0
# Name: num, dtype: float64
#或者
print(df1.groupby('key1')['num'].mean())
# key1
# A 7.5
# B 6.0
# C 5.0
# Name: num, dtype: float64
#as_index=False
print(df1.groupby('key1',as_index=False)['num'].mean())
# key1 num
# 0 A 7.5
# 1 B 6.0
# 2 C 5.0
"""
需求:计算每种的差值,
1.上表中的聚合函数不能满足于我们的需求,我们需要使用自定义的聚合函数
2.在分组对象中,使用我们自定义的聚合函数
"""
def diff_value(arr):
return arr.max() - arr.min()
#使用自定义聚合函数,我们需要将函数传递给agg或aggregate方法
print(df1.groupby('key1')['num'].agg(diff_value))
# key1
# A 1
# B 0
# C 0
# Name: num, dtype: int64
【注】:部分资源来源于网络,若侵犯了您的权利,请与作者联系,感谢!