文章目录
1、pandas的安装
python环境下直接使用pip或者conda安装
pip install pandas
conda install pandas
2、pandas的介绍
pandas是基于numpy的一种工具,该工具是为了解决数据分析任务而创建的。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。
pandas基于两种数据类型:series与dataframe
3、Series对象
Series是pandas中最基本的对象,类似于一维数组。和数组不同的是,Series能为数据自定义索引,然后通过索引来访问数组中的数据
3.1 创建series对象
In [1]: import pandas as pd
In [2]: pd.Series([1,2,3,4]) # 使用一维数组创建,使用默认索引,[0,1,2,3....]
Out[2]:
0 1
1 2
2 3
3 4
dtype: int64
# 使用一维数组创建,自定义标签索引,["a","b","c","d"]
In [3]: pd.Series([1,2,3,4], index=list("abcd"))
Out[3]:
a 1
b 2
c 3
d 4
dtype: int64
In [4]: dic = {"name": "mike", "age": 10, "sex": "male"}
In [5]: sel = pd.Series(dic) # 利用字典创建,键会自动变成标签索引
In [6]: sel
Out[6]:
name mike
age 10
sex male
dtype: object
In [7]: sel.index.tolist() # 获取标签索引
Out[7]: ['name', 'age', 'sex']
In [8]: sel.values.tolist() # 获取值
Out[8]: ['mike', 10, 'male']
In [11]: list(sel.iteritems()) # 获取标签索引键值对
Out[11]: [('name', 'mike'), ('age', 10), ('sex', 'male')]
3.2 series对象的索引和切片
In [12]: sel = pd.Series([1,2,3,4], index=list("abcd"))
In [13]: sel
Out[13]:
a 1
b 2
c 3
d 4
dtype: int64
In [14]: print("标签索引", sel['c']) # 利用标签索引取值
标签索引 3
In [15]: print("位置索引", sel[2]) # 利用位置索引取值
位置索引 3
In [16]: sel[["a","d"]] # 利用标签索引获取不连续的多个值
Out[16]:
a 1
d 4
dtype: int64
In [17]: sel[[0,3]] # 利用位置索引获取不连续的多个值
Out[17]:
a 1
d 4
dtype: int64
In [18]: sel["a":"d"] # 利用标签索引切片获取连续的多个值,注意是左右都包含
Out[18]:
a 1
b 2
c 3
d 4
dtype: int64
In [19]: sel[0:3] # 利用位置索引切片获取连续的多个值,注意是左包含右不包含
Out[19]:
a 1
b 2
c 3
dtype: int64
In [20]: sel.index = list("bcda") # index,重新定义标签索引
In [21]: sel
Out[21]:
b 1
c 2
d 3
a 4
dtype: int64
# reindex,生成一个新的Series,原Series有的索引则取对应的值,没有的索引则用NaN填充。
In [22]: sel1 = sel.reindex(list("abcdefa"))
In [23]: sel1
Out[23]:
a 4.0
b 1.0
c 2.0
d 3.0
e NaN
f NaN
a 4.0
dtype: float64
In [24]: sel.drop(["a","c"]) # 删除指定索引的值,注意是标签索引,而不是位置索引,也不是元素值
Out[24]:
b 1
d 3
dtype: int64
3.3 series的算术运算操作
- series的算术运算都是基于索引(index)进行的,支持加减乘除等运算。
- pandas会根据索引对相应的数据进行计算,结果会以浮点数的形式存储,避免丢失精度。
- pandas如果在两个series里找不到相同的索引,对应的位置则会返回一个空值 NaN。
In [25]: a = pd.Series([1,2,3,4], index=list("abcd"))
In [26]: b = pd.Series([2,4,6,8], index=list("bcde"))
In [27]: a+b # 对应索引的数值相加,没有相同索引的地方返回NaN
Out[27]:
a NaN
b 4.0
c 7.0
d 10.0
e NaN
dtype: float64
In [28]: a*b # 对应索引的数值相乘,没有相同索引的地方返回NaN
Out[28]:
a NaN
b 4.0
c 12.0
d 24.0
e NaN
dtype: float64
In [29]: a[a>2] # 和数组类似,输出大于2的元素
Out[29]:
c 3
d 4
dtype: int64
In [30]: a*2 # a对应的所有数值都乘以2
Out[30]:
a 2
b 4
c 6
d 8
dtype: int64
4、DataFrame对象
4.1 创建DataFrame对象
In [35]: import pandas as pd
In [36]: import numpy as np
# 使用二维数组创建, 三行四列的数组,行索引(index)需要3个,列索引(columns)需要4个
In [37]: pd.DataFrame([[1,2,3,4],[5,6,7,8],[2,4,6,8]], index=[1,2,3], columns=list("abcd"))
Out[37]:
a b c d
1 1 2 3 4
2 5 6 7 8
3 2 4 6 8
# 使用字典创建,行索引由index决定,列索引由字典的键决定
In [38]: dic = {"name": ["mike", "lucy", "peter"],
...: "age": [10, 12, 14],
...: "sex": ["boy", "girl", "boy"]}
In [39]: pd.DataFrame(dic, index=[1,2,3])
Out[39]:
name age sex
1 mike 10 boy
2 lucy 12 girl
3 peter 14 boy
In [40]: df = pd.DataFrame.from_dict(dic) # 使用from_dict创建,行索引默认从0开始
In [41]: df
Out[41]:
name age sex
0 mike 10 boy
1 lucy 12 girl
2 peter 14 boy
In [42]: df.to_dict() # to_dict()方法将DataFrame对象转换为字典
Out[42]:
{'name': {0: 'mike', 1: 'lucy', 2: 'peter'},
'age': {0: 10, 1: 12, 2: 14},
'sex': {0: 'boy', 1: 'girl', 2: 'boy'}}
4.2 DataFrame的常用属性和方法
In [41]: df
Out[41]:
name age sex
0 mike 10 boy
1 lucy 12 girl
2 peter 14 boy
In [43]: df.shape # 获取形状---行数和列数
Out[43]: (3, 3)
In [44]: df.dtypes # 获取数据的类型
Out[44]:
name object
age int64
sex object
dtype: object
In [45]: df.ndim # 获取维度
Out[45]: 2
In [46]: df.values # 获取值
Out[46]:
array([['mike', 10, 'boy'],
['lucy', 12, 'girl'],
['peter', 14, 'boy']], dtype=object)
In [47]: df.index.tolist() # 获取行索引
Out[47]: [0, 1, 2]
In [48]: df.columns.tolist() # 获取列索引
Out[48]: ['name', 'age', 'sex']
In [49]: df.info() # 展示df的概览信息
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 3 columns):
name 3 non-null object
age 3 non-null int64
sex 3 non-null object
dtypes: int64(1), object(2)
memory usage: 152.0+ bytes
In [50]: df.head(2) # 显示头2行,默认显示5行
Out[50]:
name age sex
0 mike 10 boy
1 lucy 12 girl
In [51]: df.tail(2) # 显示后2行,默认显示5行
Out[51]:
name age sex
1 lucy 12 girl
2 peter 14 boy
In [52]: df.sample(2) # 随机抽取2行
Out[52]:
name age sex
2 peter 14 boy
0 mike 10 boy
In [53]: df.sort_values(by="name", ascending=False) # 按照指定列进行排序
Out[53]:
name age sex
2 peter 14 boy
0 mike 10 boy
1 lucy 12 girl
In [54: df["sex"].value_counts() # 统计指定字段中每个值的总数
Out[54]:
boy 2
girl 1
Name: sex, dtype: int64
In [55]: df.describe() # 展示df 数值类型字段的统计信息
Out[55]:
age
count 3.0
mean 12.0
std 2.0
min 10.0
25% 11.0
50% 12.0
75% 13.0
max 14.0
4.3 DataFrame的索引和切片
- df.loc[],根据标签索引取值
- df.iloc[],根据位置索引取值
- 建议使用loc和iloc方法进行取值,这样对索引类型会一目了然。
In [62]: dic = {"name": ["mike", "lucy", "peter"],
...: "age": [10, 12, 14],
...: "sex": ["boy", "girl", "boy"]}
In [63]: df = pd.DataFrame(dic,index=["1","2","3"])
In [64]: df
Out[64]:
name age sex
1 mike 10 boy
2 lucy 12 girl
3 peter 14 boy
In [65]: df[1:3][["name","age"]] # 取连续多行的某两列,注意[1:3]是行位置索引,不是行标签索引
Out[65]:
name age
2 lucy 12
3 peter 14
In [66]: df[1:3] # 取连续多行
Out[66]:
name age sex
2 lucy 12 girl
3 peter 14 boy
In [67]: df[0:1] # 取单独一行
Out[67]:
name age sex
1 mike 10 boy
In [68]: df[["name","age"]] # 取多列,注意是两个方括号 [[]]
Out[68]:
name age
1 mike 10
2 lucy 12
3 peter 14
In [69]: df[["name"]] # 取单独一列,返回的是DataFrame类型
Out[69]:
name
1 mike
2 lucy
3 peter
In [70]: df["name"] # 取单独一列,返回的是Series类型
Out[70]:
1 mike
2 lucy
3 peter
Name: name, dtype: object
In [71]: df.loc[["1","3"],["name","age"]] # [[行,行],[列,列]],取不连续的多行和多列
Out[71]:
name age
1 mike 10
3 peter 14
In [72]: df.loc["1":"3",["name","age"]] # [行:行,[列,列]],取连续的多行和不连续的多列
Out[72]:
name age
1 mike 10
2 lucy 12
3 peter 14
In [73]: df.loc['1',["name","age"]] # 取某一行,多列
Out[73]:
name mike
age 10
Name: 1, dtype: object
In [74]: df.loc['1',:] # 取某一行,所有列
Out[74]:
name mike
age 10
sex boy
Name: 1, dtype: object
In [75]: df.loc['1','name'] # 取某一行,某一列
Out[75]: 'mike'
In [76]: df.iloc[[0,2],[0,2]] # [[行,行],[列,列]],取不连续的多行和多列
Out[76]:
name sex
1 mike boy
3 peter boy
In [77]: df.iloc[0:2,[0,2]] # [行:行,[列,列]],取连续的多行和不连续的多列
Out[77]:
name sex
1 mike boy
2 lucy girl
In [78]: df.iloc[0,[0,2]] # 取某一行,多列
Out[78]:
name mike
sex boy
Name: 1, dtype: object
In [79]: df.iloc[0,:] # 取某一行,所有列
Out[79]:
name mike
age 10
sex boy
Name: 1, dtype: object
In [80]: df.iloc[:,1] # 取某一列
Out[80]:
1 10
2 12
3 14
Name: age, dtype: int64
In [81]: df.iloc[0,2] # 取某一行,某一列
Out[81]: 'boy'
df.iloc[0,2] = "girl" # 通过索引修改值
4.4 DataFrame修改行、列索引
In [82]: df = pd.DataFrame(np.arange(9).reshape(3,3),index=["a","b","c"],columns=["a","b","c"])
In [83]: df.index = ["aa", "bb", "cc"] # 重新定义行索引
In [84]: df.columns = ["aa", "bb", "cc"] # 重新定义列索引
In [85]: df
Out[85]:
aa bb cc
aa 0 1 2
bb 3 4 5
cc 6 7 8
In [86]: df = pd.DataFrame(np.arange(9).reshape(3,3),index=["a","b","c"],columns=["a","b","c"])
# 使用rename分别重定义行索引和列索引,支持单个修改
In [87]: df.rename(index={"a":"aa"},columns={"b":"bb"})
Out[87]:
a bb c
aa 0 1 2
b 3 4 5
c 6 7 8
In [88]: df = df.set_index("a", drop=False) # 指定某一列的值作为行索引,drop=False表示保留该列
In [89]: df
Out[89]:
a b c
a
0 0 1 2
3 3 4 5
6 6 7 8
In [90]: df.index.name = None # 去除索引的名字 a
In [91]: df
Out[91]:
a b c
0 0 1 2
3 3 4 5
6 6 7 8
4.5 DataFrame添加数据和删除数据
In [92]: df = pd.DataFrame(np.arange(9).reshape(3,3),index=["a","b","c"],columns=["a","b","c"])
In [93]: df['d'] = [1,2,3] # 类似字典添加元素,在DataFrame后面添加一列,元素个数需要与行数一致
In [94]: df
Out[94]:
a b c d
a 0 1 2 1
b 3 4 5 2
c 6 7 8 3
In [96]: df.insert(1,"e",[1,2,3]) # insert,在指定列位置添加一列
In [97]: df
Out[97]:
a e b c d
a 0 1 1 2 1
b 3 2 4 5 2
c 6 3 7 8 3
In [100]: df = pd.DataFrame(np.arange(9).reshape(3,3),index=["a","b","c"],columns=["a","b","c"]
In [101]: new = pd.DataFrame({"a":2,"b":3,"c":4},index=[0])
# append,在原数据最后添加数据,需要重新赋值给原对象,ignore_index表示忽略自身的索引
In [102]: df = df.append(new, ignore_index=True)
In [103]: df
Out[103]:
a b c
0 0 1 2
1 3 4 5
2 6 7 8
3 2 3 4
# [0],要删除数据的索引,axis=0表示删除行,inplace=False 表示不在当前df执行此操作
In [105]: df.drop([0],axis=0,inplace=False)
Out[105]:
a b c
1 3 4 5
2 6 7 8
3 2 3 4
In [106]: df
Out[106]:
a b c
0 0 1 2
1 3 4 5
2 6 7 8
3 2 3 4
# ["a"],要删除数据的索引,axis=1表示删除列,inplace=True 表示在当前df执行此操作
In [107]: df.drop(["a"],axis=1,inplace=True)
In [108]: df
Out[108]:
b c
0 1 2
1 4 5
2 7 8
3 3 4
5、 数据处理
5.1 去除空值数据
# Series去除空值
In [109]: import pandas as pd
In [110]: from numpy import nan as NaN
In [111]: a = pd.Series([2,4,NaN,5,NaN])
In [112]: a
Out[112]:
0 2.0
1 4.0
2 NaN
3 5.0
4 NaN
dtype: float64
In [113]: a.dropna() # dropna(),去除空值,返回去除后的对象
Out[113]:
0 2.0
1 4.0
3 5.0
dtype: float64
In [114]: a = pd.Series([2,4,NaN,5,NaN])
In [115]: a.notnull() # notnull(),判断是否为空值,不是空值则在相应位置输出 True
Out[115]:
0 True
1 True
2 False
3 True
4 False
dtype: bool
In [116]: a.isnull() # isnull(),判断是否为空值,是空值则在相应位置输出 True
Out[116]:
0 False
1 False
2 True
3 False
4 True
dtype: bool
In [117]: a[a.notnull()] # 过滤空值,效果同dropna()
Out[117]:
0 2.0
1 4.0
3 5.0
dtype: float64
# DataFrame去除空值
In [118]: n = [[1,2,3],[NaN,NaN,3],[NaN,NaN,NaN],[6,7,NaN]]
In [119]: df = pd.DataFrame(n)
In [120]: df
Out[120]:
0 1 2
0 1.0 2.0 3.0
1 NaN NaN 3.0
2 NaN NaN NaN
3 6.0 7.0 NaN
In [121]: df.dropna() # 默认去除所有包含NaN的行
Out[121]:
0 1 2
0 1.0 2.0 3.0
In [123]: df.dropna(how="all") # how="all",只有全部为NaN的行,才会去除;默认为how="any"
Out[123]:
0 1 2
0 1.0 2.0 3.0
1 NaN NaN 3.0
3 6.0 7.0 NaN
In [124]: df.dropna(how="all",axis=1) # how="all",axis=1,全部为NaN的列才会去除,默认为axis=0
Out[124]:
0 1 2
0 1.0 2.0 3.0
1 NaN NaN 3.0
2 NaN NaN NaN
3 6.0 7.0 NaN
In [125]: df.dropna(how="any",axis=1) # how="any",axis=1,去除所有包含NaN的列,默认为axis=0
Out[125]:
Empty DataFrame
Columns: []
Index: [0, 1, 2, 3]
In [126]: df.dropna(thresh=2) # thresh=2,至少有2个NaN的行才会去除
Out[126]:
0 1 2
0 1.0 2.0 3.0
3 6.0 7.0 NaN
5.2 填充缺失数据
In [120]: df
Out[120]:
0 1 2
0 1.0 2.0 3.0
1 NaN NaN 3.0
2 NaN NaN NaN
3 6.0 7.0 NaN
In [128]: df.fillna(0, inplace=False) # 用常数来填充NaN,inplace=True在当前df执行操作
Out[128]:
0 1 2
0 1.0 2.0 3.0
1 0.0 0.0 3.0
2 0.0 0.0 0.0
3 6.0 7.0 0.0
In [129]: df.fillna({0:0,1:11,2:22}) # 通过字典给不同的列填充不同的常数
Out[129]:
0 1 2
0 1.0 2.0 3.0
1 0.0 11.0 3.0
2 0.0 11.0 22.0
3 6.0 7.0 22.0
In [130]: df.fillna(df.mean()) # 填充平均值
Out[130]:
0 1 2
0 1.0 2.0 3.0
1 3.5 4.5 3.0
2 3.5 4.5 3.0
3 6.0 7.0 3.0
In [131]: df.iloc[:,1].fillna(0) # 只填充指定的列
Out[131]:
0 2.0
1 0.0
2 0.0
3 7.0
Name: 1, dtype: float64
# method='ffill',用前面的值来填充;limit=1,限制填充的行数
In [132]: df.fillna(method='ffill',limit=1)
Out[132]:
0 1 2
0 1.0 2.0 3.0
1 1.0 2.0 3.0
2 NaN NaN 3.0
3 6.0 7.0 NaN
# method='bfill',用后面的值来填充,axis=1,修改填充方向
In [133]: df.fillna(method='bfill',axis=1)
Out[133]:
0 1 2
0 1.0 2.0 3.0
1 3.0 3.0 3.0
2 NaN NaN NaN
3 6.0 7.0 NaN
5.3 去除重复数据
In [134]: n = [[1,2,3],[1,2,3],[4,5,6],[4,7,8]]
In [135]: df = pd.DataFrame(n,columns=list("abc"))
In [136]: df
Out[136]:
a b c
0 1 2 3
1 1 2 3
2 4 5 6
3 4 7 8
In [137]: df.duplicated() # duplicated(),判断每一行是否重复,返回bool值
Out[137]:
0 False
1 True
2 False
3 False
dtype: bool
In [138]: df.drop_duplicates() # drop_duplicates(),去除全部的重复行
Out[138]:
a b c
0 1 2 3
2 4 5 6
3 4 7 8
In [139]: df.drop_duplicates(["a"]) # drop_duplicates(["a"]),去除指定列重复的行
Out[139]:
a b c
0 1 2 3
2 4 5 6
In [140]: df.drop_duplicates("a",keep="last") # keep="last",保留重复行中的最后一行
Out[140]:
a b c
1 1 2 3
3 4 7 8
6、数据合并和连接
数据合并、连接有三种方式:join,merge,concat
具体区别详见:https://blog.csdn.net/weixin_42384784/article/details/105188799
7、时间序列
pd.date_range(start, end, periods, freq, closed) ,其中start, end, periods必须至少指定其中的两个参数值
- start, end 开始结束时间
- periods ,分成的时间个数
- freq,默认为“D” ,时间序列频率,有 D、B、H、T、S、M等可选参数。
- closed,默认为None, 包含开始结束时间,为left时包含结束时间,不包含结束时间,为right时包含结束时间,不包含开始时间。
In [141]: pd.date_range(start="20200329",end="20200405") # 默认freq="D"
Out[141]:
DatetimeIndex(['2020-03-29', '2020-03-30', '2020-03-31', '2020-04-01',
'2020-04-02', '2020-04-03', '2020-04-04', '2020-04-05'],
dtype='datetime64[ns]', freq='D')
In [142]: pd.date_range(start="20200329",end="20200405",closed="left") # 不包含2020-04-05
Out[142]:
DatetimeIndex(['2020-03-29', '2020-03-30', '2020-03-31', '2020-04-01',
'2020-04-02', '2020-04-03', '2020-04-04'],
dtype='datetime64[ns]', freq='D')
# 把这段时间等分成10份,此时 freq=None
In [143]: pd.date_range(start="20200329",end="20200405",periods=10)
Out[143]:
DatetimeIndex(['2020-03-29 00:00:00', '2020-03-29 18:40:00',
'2020-03-30 13:20:00', '2020-03-31 08:00:00',
'2020-04-01 02:40:00', '2020-04-01 21:20:00',
'2020-04-02 16:00:00', '2020-04-03 10:40:00',
'2020-04-04 05:20:00', '2020-04-05 00:00:00'],
dtype='datetime64[ns]', freq=None)
In [144]: pd.date_range(start="20200329", periods=10, freq="5D") # 10个时间,频率为5天
Out[144]:
DatetimeIndex(['2020-03-29', '2020-04-03', '2020-04-08', '2020-04-13',
'2020-04-18', '2020-04-23', '2020-04-28', '2020-05-03',
'2020-05-08', '2020-05-13'],
dtype='datetime64[ns]', freq='5D')
In [145]: pd.date_range(start="20200329", periods=10)
Out[145]:
DatetimeIndex(['2020-03-29', '2020-03-30', '2020-03-31', '2020-04-01',
'2020-04-02', '2020-04-03', '2020-04-04', '2020-04-05',
'2020-04-06', '2020-04-07'],
dtype='datetime64[ns]', freq='D')
df.truncate(before, after),将df里面before指定日期之前的值全部过滤掉,after指定日期之后的值全部过滤掉。
df.truncate(before="2020-03-29") # 过滤 2020-03-29 之前的数据,得到2020-03-29之后的数据
df.truncate(after="2020-03-29") # 过滤 2020-03-29 之后的数据,得到2020-03-29之前的数据
8、分组聚合
In [146]: dic = {"name": ["mike", "lucy", "peter"],
...: "age": [10, 12, 12],
...: "sex": ["boy", "girl", "boy"]}
In [147]: df = pd.DataFrame(dic,index=["1","2","3"])
In [148]: df_group = df.groupby("sex") # 根据 sex这一列进行分组
In [149]: df_group_age = df.groupby(["sex","age"]) # 根据多列进行分组
In [150]: df_group.groups # 查看分组
Out[150]:
{'boy': Index(['1', '3'], dtype='object'),
'girl': Index(['2'], dtype='object')}
In [151]: df_group.count() # 查看分组后其它列的数量
Out[151]:
name age
sex
boy 2 2
girl 1 1
In [152]: for name, group in df_group: # 查看分组具体情况
...: print(name) # 组的名字
...: print(group) # 组的具体内容
boy
name age sex
1 mike 10 boy
3 peter 12 boy
girl
name age sex
2 lucy 12 girl
In [153]: df_group.get_group("boy") # 选择具体分组
Out[153]:
name age sex
1 mike 10 boy
3 peter 12 boy
常用的聚合函数: