数据分析(Pandas模块:表计算与数据分析)
注意:在pandas中,axis=1表示横坐标,axis=0表示纵坐标。特殊:drop和take函数坐标则相反!!!
一、pandas简单介绍
1、pandas是一个强大的Python数据分析的工具包。
2、pandas是基于NumPy构建的。
3、pandas的主要功能
-
- 具备对其功能的数据结构DataFrame、Series
- 集成时间序列功能
- 提供丰富的数学运算和操作
- 灵活处理缺失数据
二、pandas安装
# 安装方法: pip install pandas # 导包 import pandas as pd
from pandas import Series,DataFrame
三、Series创建
Series是一种类似于一位数组的对象,由一组数据和一组与之相关的数据标签(索引)组成。
两种创建方式: 由列表创建 默认索引为0到N-1的整数型索引 通过numpy数组创建 # 使用列表创建Series Series(data=[1,2,3]) #结果 >>> 0 1 1 2 2 3 dtype: int64 # 还可以通过设置index参数指定索引 s = Series(data=[1,2,3], index=["a","b","c"]) #结果 >>> a 1 b 2 c 3 dtype: int64 # 通过nunpy数组创建 Series(data=np.random.randint(0,100,size=(3,))) # 结果 >>> 0 49 1 85 2 11 dtype: int32 # 查看索引"c"的行 s["c"] #结果 3
四、Series支持数组的特性
- 从ndarray创建Series:Series(arr)
- 与标量运算:sr*2
- 两个Series运算:sr1+sr2
- 索引:sr[0], sr[[1,2,4]]
- 切片:sr[0:2](切片依然是视图形式)
- 通用函数:np.abs(sr)
- 布尔值过滤:sr[sr>0]
4.1 使用s.head(),tail()分别查看前n个和后n个值:
# 实验准备: s = Series(data=[1,2,3], index=["a","b","c"]) # 结果 >>> a 1 b 2 c 3 dtype: int64 # 查看前2个值 s.head(2) # s.head()默认查看5个 # 结果 >>> a 1 b 2 dtype: int64 # 查看最后2个值 s.tail(2) #结果 >>> b 2 c 3 dtype: int64
4.2 对Series元素进行去重:
s = Series(data=[1,1,2,2,3,4,5,6,6,6,7,6,6,7,8]) s.unique() #结果: >>>array([1, 2, 3, 4, 5, 6, 7, 8], dtype=int64)
五、Series的统计函数:
- mean() #求平均数
- sum() #求和
- cumsum() #累加
六、Series支持字典的特性(标签)
- 从字典创建Series:Series(dic),
- in运算:’a’ in sr、for x in sr
- 键索引:sr['a'], sr[['a', 'b', 'd']]
- 键切片:sr['a':'c']
- 其他函数:get('a', default=0)等
In [12]: s = pd.Series(0,index=['a','b','c','d']) In [13]: s.a Out[13]: 0 In [14]: v = pd.Series({'a':1,'b':2}) In [15]: v.a Out[15]: 1 In [16]: v.b Out[16]: 2 In [17]: v[0] Out[17]: 1 In [18]: s*2 Out[18]: a 0 b 0 c 0 d 0 dtype: int64 In [19]: v*2 Out[19]: a 2 b 4 dtype: int64
七、Series的整数索引
整数索引的pandas对象往往会使新手抓狂。
例:
-
- sr = np.Series(np.arange(4.))
- sr[-1]
如果索引是整数类型,则根据整数进行数据操作时总是面向标签的。
- loc属性 以标签解释
- iloc属性 以下标解释
八、Series数据对齐
pandas在运算时,会按索引进行对齐然后计算。如果存在不同的索引,则结果的索引是两个操作数索引的并集。 例: sr1 = pd.Series([12,23,34], index=['c','a','d']) sr2 = pd.Series([11,20,10], index=['d','c','a',]) sr1+sr2 sr3 = pd.Series([11,20,10,14], index=['d','c','a','b']) sr1+sr3 如何在两个Series对象相加时将缺失值设为0? sr1.add(sr2, fill_value=0) 灵活的算术方法:add, sub, div, mul
使得两个Series进行相加:
- 当索引没有对应的值时,可能出现缺失数据显示NaN(not a number)的情况
- 在运算中自动对齐不同索引的数据,如果索引不对应,则补NaN
# 两个Series进行相加
s1 = Series(data=[1,2,3,4],index=['a','b','c','d'])
s2 = Series(data=[1,2,3,4],index=['a','b','e','d'])
s = s1 + s2
#结果:
>>>
a 2.0 b 4.0 c NaN d 8.0 e NaN dtype: float64
九、Series缺失数据
1、缺失数据:使用NaN(Not a Number)来表示缺失数据。其值等于np.nan。内置的None值也会被当做NaN处理。
2、处理缺失数据的相关方法:
-
- dropna() 过滤掉值为NaN的行
- fillna() 填充缺失数据
- isnull() 返回布尔数组,缺失值对应为True
- notnull() 返回布尔数组,缺失值对应为False
3、过滤缺失数据:sr.dropna() 或 sr[data.notnull()]
4、填充缺失数据:fillna(0)
# 检测不为空则返回True s.notnull() #结果: >>>a True b True c False d True e False dtype: bool # 检测为空则返回True,与notnull用法相反 s.isnull() #结果 >>>a False b False c True d False e True dtype: bool # 如果将布尔值作为Serrise的索引,则只保留True对应的元素值 s[[True,True,False,False,True]] #结果 >>>a 2.0 b 4.0 e NaN dtype: float64 # 索引为True返回 s[s.notnull()] #结果 >>>a 2.0 b 4.0 d 8.0 dtype: float64
十、DataFrame创建
DataFrame是一个【表格型】的数据结构:
DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维
DataFrame既有行索引,也有列索引
行索引:index
列索引:columns
值:values
DataFrame的创建 最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一【列】的名称,以字典的值(一个数组)作为每一列。
此外,DataFrame会自动加上每一行的索引。
使用字典创建的DataFrame后,则columns参数将不可被使用。
同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。
DataFrame是一个表格型的数据结构,含有一组有序的列。 DataFrame可以被看做是由Series组成的字典,并且共用一个索引。 创建方式: pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]}) pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']), 'two':pd.Series([1,2,3,4],index=['b','a','c','d'])}) …… csv文件读取与写入: df.read_csv('E:\算法\day110 Numpy、Pandas模块\601318.csv') df.to_csv()
10.1 创建DataFrame:
# 方式一:通过字典创建DataFrame dic = { '张三':[150,150,150,150], '李四':[0,0,0,0] } df = DataFrame(data=dic,index=['语文','数学','英语','理综']) #结果 >>> 张三 李四 语文 150 0 数学 150 0 英语 150 0 理综 150 0 # 方式二:创建DataFrame DataFrame(data=np.random.randint(60,100,size=(3,4))) #结果 >>> 0 1 2 3 0 70 63 66 89 1 80 79 94 79 2 86 83 63 79 # 创建DataFrame,并指定行索引(index)与列索引(columns) df = DataFrame(data=np.random.randint(60,100,size=(3,4)),index=['A','B','C'],columns=['a','b','c','d']) #结果: >>> a b c d A 65 93 91 91 B 70 82 65 96 C 72 93 81 77
十、DataFrame查看数据
查看数据常用属性及方法:
index 获取索引
T 转置
columns 获取列索引
values 获取值数组
describe() 获取快速统计
DataFrame各列name属性:列名
rename(columns={})
# DataFrame的values属性 df.values #结果: >>>array([[65, 93, 91, 91], [70, 82, 65, 96], [72, 93, 81, 77]]) # DataFrame的index属性 df.index #结果 >>>Index(['A', 'B', 'C'], dtype='object') # DataFrame的columns属性 df.columns #结果 >>>Index(['a', 'b', 'c', 'd'], dtype='object')
十一、DataFrame索引和切片
1、DataFrame有行索引和列索引。
2、DataFrame同样可以通过标签和位置两种方法进行索引和切片。
3、DataFrame使用索引切片:
-
- 方法1:两个中括号,先取列再取行。 df['A'][0]
- 方法2(推荐):使用loc/iloc属性,一个中括号,逗号隔开,先取行再取列。
loc属性:解释为标签
iloc属性:解释为下标
向DataFrame对象中写入值时只使用方法2
行/列索引部分可以是常规索引、切片、布尔值索引、花式索引任意搭配。(注意:两部分都是花式索引时结果可能与预料的不同)
通过标签获取: df['A'] df[['A', 'B']] df['A'][0] df[0:10][['A', 'C']] df.loc[:,['A','B']] #行是所有的行,列取是A和B的 df.loc[:,'A':'C'] df.loc[0,'A'] df.loc[0:10,['A','C']] 通过位置获取: df.iloc[3] df.iloc[3,3] df.iloc[0:3,4:6] df.iloc[1:5,:] df.iloc[[1,2,4],[0,3]]、 通过布尔值过滤:
df[df['A']>0]
df[df['A'].isin([1,3,5])]
df[df<0] = 0
11.1 对列进行索引:
# 可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名 df = DataFrame(data=np.random.randint(60,100,size=(3,4)),index=['A','B','C'],columns=['a','b','c','d']) #结果: >>> a b c d A 73 73 83 79 B 67 76 63 69 C 86 77 79 82 #修改列索引 df.columns = ['a','c','b','d'] #结果 >>> a c b d A 73 73 83 79 B 67 76 63 69 C 86 77 79 82 # 获取前两列 df[["a","c"]] #结果 >>>a c A 73 73 B 67 76 C 86 77
11.2 对行进行索引:
# 通过隐式索引取值(iloc) df.iloc[0] #结果 >>>a 73 c 73 b 83 d 79 Name: A, dtype: int32 # 通过显示索引取值(loc) df.loc["A"] #结果 >>>a 73 c 73 b 83 d 79 Name: A, dtype: int32 # 通过索引获取多个值,获取行 df.loc[["A", "B"]] #结果: >>> a c b d A 73 73 83 79 B 67 76 63 69 # 获取某一个值,第二行第三个值 df.iloc[1,2] #结果 >>>63 # 索引获取多个值(行索引在前,列索引在后) df.loc[["B","C"],"b"] #结果 >>>B 63 C 79 Name: b, dtype: int32
11.3 DataFrame切片操作:
DataFrame切片操作 索引表示的是列索引 切片表示的是行切片 #实验准备 print(df) #结果: >>> a c b d A 73 73 83 79 B 67 76 63 69 C 86 77 79 82 # 获取前2行 df[0:2] #结果 a c b d A 73 73 83 79 B 67 76 63 69 # 获取前2列 df.iloc[:,0:2] #结果 >>>a c A 73 73 B 67 76 C 86 77
11.4 DataFrame的运算:
DataFrame之间的运算同Series一样: 在运算中自动对齐不同索引的数据 如果索引不对应,则补NaN # DataFrame的相加运算 df + df #结果: >>>a c b d A 146 146 166 158 B 134 152 126 138 C 172 154 158 164
十二、DataFrame数据对齐与缺失数据
DataFrame对象在运算时,同样会进行数据对齐,行索引与列索引分别对齐。
结果的行索引与列索引分别为两个操作数的行索引与列索引的并集。
DataFrame处理缺失数据的相关方法:
- dropna(axis=0,where=‘any’,…) 过滤掉值为NaN的行
- fillna() 填充缺失数据
- isnull() 返回布尔数组,缺失值对应为True
- notnull() 返回布尔数组,缺失值对应为False
12.1 pandas中None与np.nan的数据类型:
None是Python自带的,其类型为python object。因此,None不能参与到任何计算中。 pandas中None与np.nan都视作np.nan # 查看None的数据类型 type(None) #结果 >>>NoneType # 查看np.nan的数据类型,nan:浮点类型 type(np.nan) #结果 >>>float # np.nan不能做运算.因为np.nan运算没有意义,返回结果还是nan np.nan + 1 #结果 >>>nan
12.2 pandas中的空值处理:
- isnull():判断空值则为True
- notnull():判断非空值则为True
- drop():过滤丢失数据
- fillna():填充丢失数据
#数据准备: # 创建DataFrame df = DataFrame(data=np.random.randint(0,100,size=(13,9))) #将某些数组元素赋值为nan df.iloc[2,4] = None df.iloc[5,5] = np.nan df.iloc[2,2] = None df.iloc[7,3] = None df.iloc[6,8] = None df #结果>>> 0 1 2 3 4 5 6 7 8 0 36 50 69.0 47.0 92.0 22.0 35 26 20.0 1 25 9 78.0 51.0 66.0 44.0 87 44 96.0 2 21 37 NaN 28.0 NaN 46.0 58 9 22.0 3 64 37 66.0 61.0 40.0 9.0 33 34 18.0 4 53 11 46.0 31.0 77.0 79.0 68 17 8.0 5 14 61 99.0 59.0 63.0 NaN 10 40 74.0 6 94 65 29.0 75.0 53.0 16.0 11 64 NaN 7 43 80 79.0 NaN 88.0 64.0 26 11 1.0 8 24 95 36.0 37.0 84.0 28.0 79 69 39.0 9 22 95 3.0 99.0 16.0 77.0 91 39 80.0 10 85 44 40.0 17.0 68.0 52.0 98 13 82.0 11 53 39 96.0 24.0 32.0 84.0 57 8 30.0 12 47 9 85.0 88.0 58.0 57.0 15 25 94.0 # 判断空值项返回True,否则返回False df.isnull() #结果>>> 0 1 2 3 4 5 6 7 8 0 False False False False False False False False False 1 False False False False False False False False False 2 False False True False True False False False False 3 False False False False False False False False False 4 False False False False False False False False False 5 False False False False False True False False False 6 False False False False False False False False True 7 False False False True False False False False False 8 False False False False False False False False False 9 False False False False False False False False False 10 False False False False False False False False False 11 False False False False False False False False False 12 False False False False False False False False False # 判断空值项返回False,否则返回True df.notnull() #结果>>> 0 1 2 3 4 5 6 7 8 0 True True True True True True True True True 1 True True True True True True True True True 2 True True False True False True True True True 3 True True True True True True True True True 4 True True True True True True True True True 5 True True True True True False True True True 6 True True True True True True True True False 7 True True True False True True True True True 8 True True True True True True True True True 9 True True True True True True True True True 10 True True True True True True True True True 11 True True True True True True True True True 12 True True True True True True True True True # any:指定行或者列,isnull + any 有True(空)则返回本行为True df.isnull().any(axis=1) #结果>>> 0 False 1 False 2 True 3 False 4 False 5 True 6 True 7 True 8 False 9 False 10 False 11 False 12 False dtype: bool # all:指定行或者列,notnull + all 本行所有True(非空)则返回本行为True df.notnull().all(axis=1) #结果>>> 0 True 1 True 2 False 3 True 4 True 5 False 6 False 7 False 8 True 9 True 10 True 11 True 12 True dtype: bool # 去除空行,保留所有非空行数据 df.loc[df.notnull().all(axis=1)] #结果>>> 0 1 2 3 4 5 6 7 8 0 36 50 69.0 47.0 92.0 22.0 35 26 20.0 1 25 9 78.0 51.0 66.0 44.0 87 44 96.0 3 64 37 66.0 61.0 40.0 9.0 33 34 18.0 4 53 11 46.0 31.0 77.0 79.0 68 17 8.0 8 24 95 36.0 37.0 84.0 28.0 79 69 39.0 9 22 95 3.0 99.0 16.0 77.0 91 39 80.0 10 85 44 40.0 17.0 68.0 52.0 98 13 82.0 11 53 39 96.0 24.0 32.0 84.0 57 8 30.0 12 47 9 85.0 88.0 58.0 57.0 15 25 94.0 # df.dropna() 过滤空值,保留没有空值的行或者列 # df.dropna() 可以选择过滤的是行还是列(默认为行):axis中0表示行,1表示的列 df.dropna(axis=0) #结果>>> 0 1 2 3 4 5 6 7 8 0 36 50 69.0 47.0 92.0 22.0 35 26 20.0 1 25 9 78.0 51.0 66.0 44.0 87 44 96.0 3 64 37 66.0 61.0 40.0 9.0 33 34 18.0 4 53 11 46.0 31.0 77.0 79.0 68 17 8.0 8 24 95 36.0 37.0 84.0 28.0 79 69 39.0 9 22 95 3.0 99.0 16.0 77.0 91 39 80.0 10 85 44 40.0 17.0 68.0 52.0 98 13 82.0 11 53 39 96.0 24.0 32.0 84.0 57 8 30.0 12 47 9 85.0 88.0 58.0 57.0 15 25 94.0 # fillna():value和method参数 # fillna() 填充函数 ffill:填充上一行对应的值,bfill:填充下一行对应的值 df.fillna(method="ffill", axis=1) #结果>>> 0 1 2 3 4 5 6 7 8 0 36.0 50.0 69.0 47.0 92.0 22.0 35.0 26.0 20.0 1 25.0 9.0 78.0 51.0 66.0 44.0 87.0 44.0 96.0 2 21.0 37.0 37.0 28.0 28.0 46.0 58.0 9.0 22.0 3 64.0 37.0 66.0 61.0 40.0 9.0 33.0 34.0 18.0 4 53.0 11.0 46.0 31.0 77.0 79.0 68.0 17.0 8.0 5 14.0 61.0 99.0 59.0 63.0 63.0 10.0 40.0 74.0 6 94.0 65.0 29.0 75.0 53.0 16.0 11.0 64.0 64.0 7 43.0 80.0 79.0 79.0 88.0 64.0 26.0 11.0 1.0 8 24.0 95.0 36.0 37.0 84.0 28.0 79.0 69.0 39.0 9 22.0 95.0 3.0 99.0 16.0 77.0 91.0 39.0 80.0 10 85.0 44.0 40.0 17.0 68.0 52.0 98.0 13.0 82.0 11 53.0 39.0 96.0 24.0 32.0 84.0 57.0 8.0 30.0 12 47.0 9.0 85.0 88.0 58.0 57.0 15.0 25.0 94.0
十三、pandas:其他常用方法(concat,merge)
- mean #求平均值 - sum #求和 - sort_index #按行或列索引排序 - sort_values #按值排序 - apply(func,axis=0) #axis=0指的是逐行,axis=1指的是逐列。 df.apply(lamada x:x.mean()) #按列求平均 df.apply(lamada x:x['high']+x["low"])/2,axis=1) #按列求平均(最高价和最低价的平均) df.apply(lamada x:x['high']+x["low"])/2,axis=1) #按列求平均(最高价和最低价的平均) - applymap(func) #将函数应用在DataFrame各个元素上 - map(func) #将函数应用在Series各个元素上
pandas的拼接分为两种: - 级联:pd.concat, pd.append - 合并:pd.merge, pd.join
13.1 使用pd.concat()级联:
pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数: - pd.concat参数: objs axis=0 keys join='outer' / 'inner':表示的是级联的方式,outer会将所有的项进行级联(忽略匹配和不匹配),而inner只会将匹配的项级联到一起,不匹配的不级联 ignore_index=False # 实验准备:准备数据 df1 = DataFrame(data=np.random.randint(0,100,size=(3,4)),index=['A','B','C'],columns=['a','b','c','d']) df2 = DataFrame(data=np.random.randint(0,100,size=(3,4)),index=['A','D','C'],columns=['a','b','e','d']) # 显示数据 display(df1,df2) #结果>>> a b c d A 23 26 89 16 B 12 82 41 15 C 99 72 72 3 a b e d A 67 76 43 82 D 68 71 77 3 C 73 6 41 37 # 匹配的级联(数据格式(index与columns)相同) pd.concat((df1,df1,df1),axis=1,join="inner") #结果:>>> a b c d a b c d a b c d A 23 26 89 16 23 26 89 16 23 26 89 16 B 12 82 41 15 12 82 41 15 12 82 41 15 C 99 72 72 3 99 72 72 3 99 72 72 3 #不匹配级联 不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致 有2种连接方式: 外连接:补NaN(默认模式) 内连接:只连接匹配的项 pd.concat((df1,df2),axis=0,join="inner") #结果:>>> a b d A 23 26 16 B 12 82 15 C 99 72 3 A 67 76 82 D 68 71 3 C 73 6 37
13.2 使用pd.merge()合并:
merge与concat的区别在于,merge需要依据某一共同的列来进行合并
使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。
注意每一列元素的顺序不要求一致
参数:
- how:out取并集 inner取交集
- on:当有多列相同的时候,可以使用on来指定使用那一列进行合并,on的值为一个列表
# 数据准备 df1 = DataFrame({'employee':['Bob','Jake','Lisa'], 'group':['Accounting','Engineering','Engineering'], }) df2 = DataFrame({'employee':['Lisa','Bob','Jake'], 'hire_date':[2004,2008,2012], }) display(df1,df2) #结果:>>> employee group 0 Bob Accounting 1 Jake Engineering 2 Lisa Engineering employee hire_date 0 Lisa 2004 1 Bob 2008 2 Jake 2012 # 一对一合并 pd.merge(df1,df2) #结果>>> employee group hire_date 0 Bob Accounting 2008 1 Jake Engineering 2012 2 Lisa Engineering 2004 # 数据准备:创建df3,df4 df3 = DataFrame({ 'employee':['Lisa','Jake'], 'group':['Accounting','Engineering'], 'hire_date':[2004,2016]}) df4 = DataFrame({'group':['Accounting','Engineering','Engineering'], 'supervisor':['Carly','Guido','Steve'] }) display(df3,df4) # 结果>>> employee group hire_date 0 Lisa Accounting 2004 1 Jake Engineering 2016 group supervisor 0 Accounting Carly 1 Engineering Guido 2 Engineering Steve # 多对一合并 pd.merge(df3,df4) #结果>>> employee group hire_date supervisor 0 Lisa Accounting 2004 Carly 1 Jake Engineering 2016 Guido 2 Jake Engineering 2016 Steve # 数据准备:创建df5,df6 df5 = DataFrame({'employee':['Bob','Jake','Lisa'], 'group':['Accounting','Engineering','Engineering']}) df6 = DataFrame({'group':['Engineering','Engineering','HR'], 'supervisor':['Carly','Guido','Steve'] }) display(df5,df6) #结果>>> employee group 0 Bob Accounting 1 Jake Engineering 2 Lisa Engineering group supervisor 0 Engineering Carly 1 Engineering Guido 2 HR Steve # merge外连接 pd.merge(df5,df6,how="outer") #结果>>> employee group supervisor 0 Bob Accounting NaN 1 Jake Engineering Carly 2 Jake Engineering Guido 3 Lisa Engineering Carly 4 Lisa Engineering Guido 5 NaN HR Steve
13.3 key的规范化:
- 当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名
- 当两张表没有可进行连接的列时,可使用left_on和right_on手动指定merge中左右两边的哪一列列作为连接的列
#数据准备 df1 = DataFrame({'employee':['Jack',"Summer","Steve"], 'group':['Accounting','Finance','Marketing']}) df2 = DataFrame({'employee':['Jack','Bob',"Jake"], 'hire_date':[2003,2009,2012], 'group':['Accounting','sell','ceo']}) display(df1,df2) #结果>>> employee group 0 Jack Accounting 1 Summer Finance 2 Steve Marketing employee group hire_date 0 Jack Accounting 2003 1 Bob sell 2009 2 Jake ceo 2012 #多个列名称相同时,需要使用on=来指定哪一个列作为key进行合成 pd.merge(df1,df2,on="employee") #结果>>> employee group_x group_y hire_date 0 Jack Accounting Accounting 2003 # 数据准备: df1 = DataFrame({'employee':['Bobs','Linda','Bill'], 'group':['Accounting','Product','Marketing'], 'hire_date':[1998,2017,2018]}) df2 = DataFrame({'name':['Lisa','Bobs','Bill'], 'hire_dates':[1998,2016,2007]}) display(df1,df2) #结果>>> employee group hire_date 0 Bobs Accounting 1998 1 Linda Product 2017 2 Bill Marketing 2018 hire_dates name 0 1998 Lisa 1 2016 Bobs 2 2007 Bill # 当两张表没有可进行连接的列时,可使用left_on和right_on手动指定merge中左右两边的哪一列列作为连接的列 pd.merge(df1,df2,left_on='employee',right_on='name') #结果>>> employee group hire_date hire_dates name 0 Bobs Accounting 1998 2016 Bobs 1 Bill Marketing 2018 2007 Bill
十四、pandas删除重复数据
使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True
- keep参数:指定保留哪一重复的行数据
- keep="first" 保留第一次重复值
- keep="last" 保留最后一次重复值
- keep=False 重复值都不保留
# 实验准备,创建DaraFrame df = DataFrame(data=np.random.randint(0,100,size=(9,5))) df.iloc[1] = [6,6,6,6,6] df.iloc[3] = [6,6,6,6,6] df.iloc[5] = [6,6,6,6,6] #结果>>> 0 1 2 3 4 0 56 27 54 71 71 1 6 6 6 6 6 2 22 57 79 94 31 3 6 6 6 6 6 4 75 16 62 81 91 5 6 6 6 6 6 6 18 38 32 52 10 7 84 50 79 76 69 8 28 14 26 97 33 # 使用drop_duplicates()函数删除重复的行 # keep="first" 保留第一次重复的行数据 df.drop_duplicates(keep="first") #结果>>> 0 1 2 3 4 0 56 27 54 71 71 1 6 6 6 6 6 2 22 57 79 94 31 4 75 16 62 81 91 6 18 38 32 52 10 7 84 50 79 76 69 8 28 14 26 97 33
十五、pandas映射与替换
15.1 替换元素(replace()):
- 单值替换
- 普通替换: 替换所有符合要求的元素:to_replace=15,value='e'
- 按列指定单值替换: to_replace={列标签:替换值} value='value'
- 多值替换
- 列表替换: to_replace=[] value=[]
- 字典替换(推荐) to_replace={to_replace:value,to_replace:value}
# 普通替换:替换所有的6为six df.replace(to_replace=6,value="six") #结果>>> 0 1 2 3 4 0 56 27 54 71 71 1 six six six six six 2 22 57 79 94 31 3 six six six six six 4 75 16 62 81 91 5 six six six six six 6 18 38 32 52 10 7 84 50 79 76 69 8 28 14 26 97 33 # 通过字典替换:替换所有的6为six df.replace(to_replace={6:"six"}) #结果 0 1 2 3 4 0 56 27 54 71 71 1 six six six six six 2 22 57 79 94 31 3 six six six six six 4 75 16 62 81 91 5 six six six six six 6 18 38 32 52 10 7 84 50 79 76 69 8 28 14 26 97 33 # 特殊替换:替换指定列中的数值替换,第三列的所有6替换成six df.replace(to_replace={3:6},value="six") #结果>>> 0 1 2 3 4 0 56 27 54 71 71 1 6 6 6 six 6 2 22 57 79 94 31 3 6 6 6 six 6 4 75 16 62 81 91 5 6 6 6 six 6 6 18 38 32 52 10 7 84 50 79 76 69 8 28 14 26 97 33
15.2 映射(map()):
map函数并不是df的方法,而是series的方法:
- map的几种类型:
- map()可以映射新一列数据
- map()中可以使用lambd表达式
- map()中可以使用方法,可以是自定义的方法
- 表达式:
- eg:map({to_replace:value})
-
注意:
- map()中不能使用sum之类的函数,for循环
- 并不是任何形式的函数都可以作为map的参数。只有当一个函数具有一个参数且有返回值,那么该函数才可以作为map的参数
# 数据准备 dic = { 'name':['jay','tom','jay'], 'salary':[9999,5000,9999] } df = DataFrame(data=dic) #结果>>> name salary 0 jay 9999 1 tom 5000 2 jay 9999 # 新增一列:给df中,添加一列,该列的值为中文名对应的英文名 # dic 自定义字段映射表 dic = { "jay": "周杰棍", "tom": "双杰伦" } df["c_name"] = df["name"].map(dic) #结果>>> name salary c_name 0 jay 9999 周杰棍 1 tom 5000 双杰伦 2 jay 9999 周杰棍 # map当做一种运算工具,至于执行何种运算,是由map函数的参数决定的(参数:lambda,函数) # 使用自定义函数 def after_sla(s): return s - (s-5000)*0.05 # 通过map函数计算salary超过5000部分的钱缴纳5%的税 df["after_salary"]= df["salary"].map(after_sla) # 结果>>> name salary c_name after_salary 0 jay 9999 周杰棍 9749.05 1 tom 5000 双杰伦 5000.00 2 jay 9999 周杰棍 9749.05 # 运算工具apply,这里运算结果同上 df["salary"].apply(after_sla) # 结果>>> 0 9749.05 1 5000.00 2 9749.05 Name: salary, dtype: float64
十六、使用聚合操作对数据异常值检测和过滤
- 使用df.std()函数可以求得DataFrame对象每一列的标准差
# 实验准备 创建一个1000行3列的df 范围(0-1),求其每一列的标准差 df = DataFrame(data=np.random.random(size=(1000,3)),columns=['A','B','C']) df.head() #结果:>>> A B C 0 0.749659 0.205499 0.314041 1 0.828922 0.730040 0.051446 2 0.127467 0.423789 0.768037 3 0.648669 0.301543 0.400714 4 0.963059 0.675478 0.722997 # 需求:对df应用筛选条件,去除标准差太大的数据:假设过滤条件为 C列数据大于两倍的C列标准差 # 获取C列数据大于两倍的C列标准差 std_twice = df["C"].std()*2 std_twice #结果>>> 0.5683930751229487 # 判断C列数据中,数值大于2倍标准差的数值为异常数值 df["C"] > std_twice # 获取异常数值行索引 indexs = df.loc[df["C"] > std_twice].index # 根据索引值,删除异常数据行 df.drop(labels=indexs,axis=0,inplace=True) //axis=0表示行 df
十七、pandas排序
使用.take()函数排序
在take函数中,axis=1表示纵坐标,axis=0表示横坐标 take()函数接受一个索引列表,用数字表示,使得df根据列表中索引的顺序进行排序 eg:df.take([1,3,4,2,5]) 可以借助np.random.permutation()函数随机排序 # 先对数据列排序,在对行进行随机打乱排序(np.random.permutation(500)) df.take([2,1,0],axis=1).take(np.random.permutation(500),axis=0) # 在打乱的DataFrame中随机获取10行 df.take([2,1,0],axis=1).take(np.random.permutation(500),axis=0)[0:10] #结果>>> C B A 875 0.410932 0.964015 0.338284 478 0.202094 0.797299 0.981498 114 0.530967 0.510114 0.041500 248 0.517917 0.491662 0.937298 410 0.289813 0.124048 0.659223 562 0.143723 0.476050 0.309460 603 0.418067 0.475892 0.817013 599 0.216818 0.482342 0.141371 480 0.373935 0.725371 0.945609 176 0.510821 0.128612 0.230764
十八、pandas数据分类处理(groupby)
数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。
数据分类处理:
-
- 分组:先把数据分为几组
- 用函数处理:为不同组的数据应用不同的函数以转换数据
- 合并:把不同组得到的结果合并起来
数据分类处理的核心:
- groupby()函数
- groups属性查看分组情况
- eg: df.groupby(by='item').groups
# 分组测试 数据准备 df = DataFrame({'item':['Apple','Banana','Orange','Banana','Orange','Apple'], 'price':[4,3,3,2.5,4,2], 'color':['red','yellow','yellow','green','green','green'], 'weight':[12,20,50,30,20,44]}) #结果>>> color item price weight 0 red Apple 4.0 12 1 yellow Banana 3.0 20 2 yellow Orange 3.0 50 3 green Banana 2.5 30 4 green Orange 4.0 20 5 green Apple 2.0 44 # 使用groupby实现分组 对item分组,返回一个分组对象 df.groupby(by="item") #结果>>> <pandas.core.groupby.DataFrameGroupBy object at 0x000001B31CF8F940> #groups属性:显示分组情况 df.groupby(by="item").groups #结果>>> {'Apple': Int64Index([0, 5], dtype='int64'), 'Banana': Int64Index([1, 3], dtype='int64'), 'Orange': Int64Index([2, 4], dtype='int64')} #方法一:给df创建一个新列,内容为各个水果的平均价格(mean()获取平平均值) df.groupby(by="item").mean()["price"] #结果>>> item Apple 3.00 Banana 2.75 Orange 3.50 Name: price, dtype: float64 # 方式二:先获取指定计算的列,效率比方法一高 mean_price_s = df.groupby(by="item")["price"].mean() mean_price_s #结果>>> item Apple 3.00 Banana 2.75 Orange 3.50 Name: price, dtype: float64 # to_dict()生层字典 dic = mean_price_s.to_dict() #结果>>> {'Apple': 3.0, 'Banana': 2.75, 'Orange': 3.5} # 添加新列, df["mean_price"] = df["item"].map(dic) #结果>>> color item price weight mean_price 0 red Apple 4.0 12 3.00 1 yellow Banana 3.0 20 2.75 2 yellow Orange 3.0 50 3.50 3 green Banana 2.5 30 2.75 4 green Orange 4.0 20 3.50 5 green Apple 2.0 44 3.00
高级数据聚合:
使用groupby分组后,也可以使用transform和apply提供自定义函数实现更多的运算
- df.groupby('item')['price'].sum() <==> df.groupby('item')['price'].apply(sum)
- transform和apply都会进行运算,在transform或者apply中传入函数即可
- transform和apply也可以传入一个lambda表达式
# 自定义函数 s为分组后的series数据类型列表 def my_mean(s): sum = 0 for i in s: sum += i return sum/s.size # transform用法,返回是映射后的结果值 df.groupby(by="item")["price"].transform(my_mean) #结果>>> 0 3.00 1 2.75 2 3.50 3 2.75 4 3.50 5 3.00 Name: price, dtype: float64 # apply用法,返回是未被映射后的结果值 df.groupby(by="item")["price"].apply(my_mean) #结果:>>> item Apple 3.00 Banana 2.75 Orange 3.50 Name: price, dtype: float64
聚合补充:
分组 df = pd.DateFrame({ 'data1':np.random.uniform(10,20,5), 'data2':np.random.uniform(-10,10,5), 'key1':list("sbbsb") 'key2': }) df.groupby('key1').mean() #做平均 df.groupby('key1').sum() #做平均 df.groupby(['key1','key2']).mean() #做平均 支持分层索引,按多列分组 df.groupby(len).mean() #传一个函数的时候,x是每一个行的索引 df.groupby(lambda x:len(x)).mean() #传一个函数的时候,x是每一个行的索引 df.groupby.groups() #取得多有的组 df.groupby.get_group() #取得一个组 聚合 df.groupby('key1').max()[['data1','data2']] #去掉key2的data1,data2,花式索引 df.groupby('key1').max()[['data1','data2']]- df.groupby('key1').min()[['data1','data2']] #去掉key2 df.groupby('key1').agg(lamada x:x.max()-x.min()) 既想看最大也可看最小 df.groupby('key1').agg([np.max,np.min]) 不同的列不一样的聚合 df.groupby('key1').agg({'data1':'min','data2':'max'}) #键是列名,值是 a=_219 #219行的代码 a.resample('3D'),mean() #3D 3天,3M就是三周 数据合并 - 数据拼接 df = df.copy() pd.concat([df,df2,df3],ignore_index=True) #不用之前的索引, pd.concat([df,df2,df3],axis=1) #列 pd.concat([df,df2,df3],keys=['a','b','c']) #不用之前的索引, df2.appeng(df3) - 数据连接 如果不指定on,默认是行索引进行join pd.merge(df,df3,on='key1') pd.merge(df,df3,on='['key1','key2'])
十九、pandas:时间对象处理
时间序列类型: 时间戳:特定时刻 固定时期:如2017年7月 时间间隔:起始时间-结束时间 Python标准库:datetime datetime.datetime.timedelta # 表示 时间间隔 dt.strftime() #f:format吧时间对象格式化成字符串 strptime() #吧字符串解析成时间对象p:parse 灵活处理时间对象:dateutil包 dateutil.parser.parse('2018/1/29') 成组处理时间对象:pandas pd.to_datetime(['2001-01-01', '2002-02-02'])
产生时间对象数组:date_range
- start 开始时间
- end 结束时间
- periods 时间长度
- freq 时间频率,默认为'D',可选H(our),W(eek),B(usiness),S(emi-)M(onth),(min)T(es), S(econd), A(year),…
二十、pandas:时间序列
1、时间序列就是以时间对象为索引的Series或DataFrame。
2、datetime对象作为索引时是存储在DatetimeIndex对象中的。
3、时间序列特殊功能:
- 传入“年”或“年月”作为切片方式
- 传入日期范围作为切片方式
- 丰富的函数支持:resample(), strftime(), ……
- 批量转换为datetime对象:to_pydatetime()
二十一、pandas:从文件读取
1、时间序列就是以时间对象作为索引
-
- 读取文件:从文件名、URL、文件对象中加载数据
- read_csv 默认分隔符为csv
- read_table 默认分隔符为\t
- read_excel 读取excel文件
2、读取文件函数主要参数:
-
- sep 指定分隔符,可用正则表达式如'\s+'
- header=None 指定文件无列名
- name 指定列名
- index_col 指定某列作为索引
- skip_row 指定跳过某些行
- na_values 指定某些字符串表示缺失值
- parse_dates 指定某些列是否被解析为日期,布尔值或列表
df = pd.read_csv("601318.csv") #默认以,为分隔符 - pd.read_csv("601318.csv",sep='\s+') #匹配空格,支持正则表达式 - pd.read_table("601318.csv",sep=',') #和df = pd.read_csv("601318.csv") 一样 - pd.read_excle("601318.xlsx") #读Excel文件 sep:指定分隔符 header = NOne,就会吧默认的表名去除 了 df.rename(column={0:'a',1:"b"}) #修改列名 pd.read_csv(index_col=0) #第0列 如果想让时间成为索引 pd.read_csv(index_col='date') #时间列 pd.read_csv(index_col='date',parse_datas=True) #时间列 parse_datas转换为时间对象,设为true是吧所有能转的都转 pd.read_csv(index_col='date',parse_datas=['date']) #知识吧date的那一列转换成时间对象 na_values=['None'] #吧表里面为None的转换成NaN,是吧字符串转换成缺失值 na_rep() #是吧缺失值nan转换成字符串 cols #指定输出的列,传入列表
二十二、pandas:写入到文件
1、写入到文件:
-
- to_csv
2、写入文件函数的主要参数:
-
- sep
- na_rep 指定缺失值转换的字符串,默认为空字符串
- header=False 不输出列名一行
- index=False 不输出行索引一列
- cols 指定输出的列,传入列表
3、其他文件类型:json, XML, HTML, 数据库
4、pandas转换为二进制文件格式(pickle):
-
- save
- load