Pandas简介
pandas是用于对数据进行分析,其需要依赖numpy模块,所以需要首先安装numpy 安装:pip install pandas 导入:import pandas as pd 主要功能: 1、具备对其功能的数据结构DataFrame、Series(即两种对象,其实有更多) 2、集成时间序列功能 3、提供丰富的数学运算和操作 4、灵活处理缺失数据Series对象
Series对象是一种类似于一维数组的对象,由一组数据和一组与之相关的数据标签(索引)组成,好像是字典和列表的结合体
创建
方式一、pd.Series(列表或数组{,index=[列表]})
sr = pd.Series([1, 3, 5, 7, 9]) """ 0 1 1 3 2 5 3 7 4 9 """ sr = pd.Series([1, 3, 5, 7, 9], index=list('abcde')) """ a 1 b 3 c 5 d 7 e 9 dtype: int64 """
方式二、pd.Series(字典)
sr = pd.Series({'a': 1, 'b': 3, 'c': 5, 'd': 7, 'e': 9}) """ a 1 b 3 c 5 d 7 e 9 dtype: int64 """
取对应下标或标签的值
sr = pd.Series({'a': 1, 'b': 3, 'c': 5, 'd': 7, 'e': 9}) """ a 1 b 3 c 5 d 7 e 9 dtype: int64 """ # 可按下标取值 print(sr[0]) # 1 # 如指定了标签,则可使用标签,字典的key print(sr['c']) # 5
属性
index属性和values属性# index属性 sr = pd.Series({'a': 1, 'b': 3, 'c': 5, 'd': 7, 'e': 9}) print(sr.index) # Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
# values属性 sr = pd.Series({'a': 1, 'b': 3, 'c': 5, 'd': 7, 'e': 9}) print(sr.values) # [1 3 5 7 9]
iloc属性:指定用下标索引
loc属性:标签索引
Series特性
数组的特性
Series支持数组(numpy)的特性,如与数值的计算、两个Series的运算,索引、切片、通用函数(如np.sqrt(sr))、布尔值过滤、统计函数
字典的特性
1、in运算: 'a' in sr:判断a是不是sr的标签之一 for x in sr:这里注意,python循环的是字典的键,而在Series中循环的是sr的值sr = pd.Series({'a': 1, 'b': 3, 'c': 5, 'd': 7, 'e': 9}) for x in sr: print(x) """ 1 3 5 7 9 """ # 如果要循环标签,可加上index,如下: for x in sr.index: print(x) """ a b c d e """
2、键索引:sr['a']、sr[['a', 'b', 'e']]
3、键切片:sr['a':'c'],注意python字典切片是不包尾,但在Series切片是包尾的
sr = pd.Series({'a': 1, 'b': 3, 'c': 5, 'd': 7, 'e': 9}) print(sr['a': 'c']) """ a 1 b 3 c 5 """
4、get函数:与字典的get是类似的sr.get('a', default=0)
5、shift(n):如果n是整数,则所有数据往下移,否则往上移
整数索引
以下情况:sr1 = pd.Series([1, 3, 5, 7, 9, 11]) sr2 = sr1[2:5] """ 2 5 3 7 4 9 """
那么sr2[2]是按下标索引还是标签索引?下面做了个测试
print(sr2[2]) # 5
得出了是按标签索引,所以默认是按标签索引,而如果要指定是按下标索引怎么办呢?用到iloc属性,如下:
print(sr2.iloc[2]) # 9
也可指定用标签索引,用loc属性
print(sr2.loc[2]) # 5
数据对齐
Series之间进行运算,是根据相同标签查找的值进行运算,如下:# 按标签进行运算,不是按下标运算 sr1 = pd.Series([12, 23, 34], index=list('cad')) sr2 = pd.Series([11, 20, 10], index=list('dca')) sr3 = sr1 + sr2 """ a 33 c 32 d 45 """
如果找不到对应的下标,则会用NaN标记,如下:
sr1 = pd.Series([12, 23, 34], index=list('cae')) sr2 = pd.Series([11, 20, 10], index=list('dca')) sr3 = sr1 + sr2 """ a 33.0 c 32.0 d NaN e NaN """
如果需要在缺失的数据上填上默认值怎么办呢?那这时候进行运算时就需要用到add、sub、div、mul等运算的fill_value,例子如下:
sr1 = pd.Series([12, 23, 34], index=list('cae')) sr2 = pd.Series([11, 20, 10], index=list('dca')) print(sr1.add(sr2, fill_value=0)) """ a 33.0 c 32.0 d 11.0 e 34.0 """
缺失数据的处理
1、sr.dropno():把Series中标记为NaN的数据丢弃sr1 = pd.Series([12, 23, 34], index=list('cae')) sr2 = pd.Series([11, 20, 10], index=list('dca')) sr3 = sr1 + sr2 print(sr3.dropna()) """ a 33.0 c 32.0 """
2、sr.fillna(值):填充一个值
3、sr.isnull():返回一个布尔数组,缺失值对应为True
sr1 = pd.Series([12, 23, 34], index=list('cae')) sr2 = pd.Series([11, 20, 10], index=list('dca')) sr3 = sr1 + sr2 """ a False c False d True e True """
4、sr.notnull():返回一个布尔数值,缺失值对应为False
注意:panads一般需要重新赋值才可以继续使用,不赋值那还是原来的值???
DataFrame
DataFrame是一个表格型的数据结构,含有一组有序的列,可以被看做是由Series组成的字典,并且共用一个索引创建方法
pd.DataFrame(字典),注意字典的值可以是一个列表,也可以是一个Series对象,例子如下df = pd.DataFrame({'one': [1, 2, 3, 4], 'two': [4, 3, 2, 1]}) df = pd.DataFrame({'one': pd.Series([1, 2, 3], index=list('abc')), 'two': pd.Series(data=[1, 2, 3, 4], index=list('bacd'))}) print(df)
但DataFrame一般是由文件读取的:
pd.read_csv:默认分隔符为逗号
pd.read_table:默认分隔符为\t
pd.read_excel:读取excel文件
有以下参数
sep:指定分隔符,可用正则表达式如'\S+'
header=None:指定文件是否有列名
names:指定列名
index_col:指定某列作为索引
skip_row:指定路过某些行
na_values:指定某此字符串用NaN表达
parse_dates:指定某些列是否被解析为日期
写入文件:df.to_csv()
参数如下:
sep:指定分隔符
na_rep:指定缺失值转换的字符串,默认为空字符串
header=False:是否保存列名
index=False:不输出行索引
cols:指定输出的列到文件
了支持其它文件类型,如:json XML HTML 数据库
也能转换为二进制文件格式(pickle):
save
load
查看数据的属性与方法
index:获取索引 T:转置 columns:获取列索引 values:获取值数组 describe():获取快速统计 rename(columns={旧列名:新列名})索引和切片
一、DataFrame有行索引和列索引 二、同样可以通过标签和下标两种方法进行索引和切片 三、使用索引和切片的方法 方法1、两个中括号,先取列再列行,df['A'][0] # A列的第0个行索引 方法2(推荐):使用loc/iloc属性,一个中括号,逗号隔开,先取行再列列。df.loc[0,'A'] 注意:向DataFrame对象中写入值时只使用方法2 标签获取: df['A']、df[['A','B']]、df['A'][0]、df.loc[:,['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[df['A']>0]、df[df['A'].isin([1,3,5])]、df[df<0] = 0 四、行/列索引部分可以是常规索引、切片、布尔值索引、花式索引任意搭配。数据对齐与缺失数据
DataFrame对象在运算时,同样会进行数据对齐,行索引与列索引分别对齐。结果的行索引与列索引分别为两个操作数的行索引与列索引的并集。 处理缺失数据的相关方法: dropna(axis=0,how='any') # axis为0时对列进行处理,1即对行处理,how为any时则其中一个为NaN则丢弃,all时则所有都为NaN才丢弃 fillna(值) isnull() notnull()其他常用方法
mean(axis=0,skipna=False):求平均值 sum(axis=1):求和 sort_index(axis,...,ascending):索引排序,ascending默认为True,则升序 sort_values(by,axis,ascending):按by参数排序 NumPy的通用函数同样适用于pandas apply(func,axis=0):将自定义函数应用在各行或各列上,func可返回标量或Seriesimport pandas as pd df = pd.read_csv('BHP1.csv') # 计算High和Low的平均价 print(df.apply(lambda x: (x['High'] + x['Low']) / 2, axis=1)) # 计算high和low的平均值,返回Series print(df.apply(lambda x: pd.Series([(x['High'] + x['Low']) / 2, (x['Open'] + x['Close']) / 2], index=['hl_mean', 'oc_mean']), axis=1))
applymap(func):将函数应用在DataFrame各个元素上
import pandas as pd df = pd.read_csv('BHP1.csv') # 将dataframe中的每个元素加1 print(df.applymap(lambda x: x + 1))
map(func):将函数应用在Series各个元素上 ,与上类似。
数据的分组与聚合
这个就相当于Excel中的分类汇总功能,但这个功能比起Excel的强大得多...... 分组:把某一列把数据拆分为若干组 聚合:组内应用某个函数分组
分组的方法:DataFrame对象.groupby(by=None,...) 按一列分组:groupby('key1') 按多列分组:groupby(['key1', 'key2']) 按索引长度分组:groupby(len) 自定义分组:groupby(函数名) 获取分组信息: groups get_group('a') for name,group in df.groupby('key') 例子如下:import pandas as pd df = pd.DataFrame({'data1': [1, 1.2, 3.4, 5.7, 8], 'data2': [10.2, 5.6, 8.7, 3.5, 8.8], 'key1': list('abbab'), 'key2': list('fgfgf')}) """ data1 data2 key1 key2 0 1.0 10.2 a f 1 1.2 5.6 b g 2 3.4 8.7 b f 3 5.7 3.5 a g 4 8.0 8.8 b f """ # 获取分组信息 # print(df.groupby('key1').groups) # {'a': Int64Index([0, 3], dtype='int64'), 'b': Int64Index([1, 2, 4], dtype='int64')} # print(df.groupby(['key1', 'key2']).groups) # {('a', 'f'): Int64Index([0], dtype='int64'), ('a', 'g'): Int64Index([3], dtype='int64'), ('b', 'f'): Int64Index([2, 4], dtype='int64'), ('b', 'g'): Int64Index([1], dtype='int64')} # 获取某一分组的值 # print(df.groupby('key1').get_group('a')) # 获取多列分组的值 # print(df.groupby(['key1', 'key2']).get_group(('a', 'f'))) for name, group in df.groupby('key1'): print(name) print(group) print('-' * 50)
自定义分组:
import pandas as pd df = pd.DataFrame({'data1': [1, 1.2, 3.4, 5.7, 8], 'data2': [10.2, -5.6, -8.7, 3.5, 8.8], 'key1': list('abbab'), 'key2': list('fgfgf'), }, index=['Alex', 'Bob', 'Celina', 'Debi', 'Egon']) # 按索引长度排序 # print(df.groupby(len).groups) # 自定义分组,按data2中正数为一组,负数为一组,此处x可理解为索引 print(df.groupby(lambda x: 'zheng' if df['data2'][x] > 0 else 'fu').groups)
聚合
聚合:分组之后需要聚合函数来应用到每一组中。 内置聚合函数: max() min() count() mean() sum() 用法:DataFrame对象.groupby(字段名).聚合函数() 自定义聚合函数:agg() 有三种用法:自定义聚合、多个聚合函数、不同列应用不同聚合函数,例子如下:import pandas as pd df = pd.DataFrame({'data1': [1, 1.2, 3.4, 5.7, 8], 'data2': [10.2, -5.6, -8.7, 3.5, 8.8], 'key1': list('abbab'), 'key2': list('fgfgf'), }, index=['Alex', 'Bob', 'Celina', 'Debi', 'Egon']) """ data1 data2 key1 key2 Alex 1.0 10.2 a f Bob 1.2 -5.6 b g Celina 3.4 -8.7 b f Debi 5.7 3.5 a g Egon 8.0 8.8 b f """ # 计算组内最大值和最小值之差 # print(df.groupby('key1').agg(lambda x: x.max() - x.min())) # 多个聚合函数,计算组内最大值、最小值以及它们之间的差 # print(df.groupby('key1').agg(['max', 'min', lambda x: x.max() - x.min()])) # 不同列应用不同的聚合函数,data1求最大值,data2求最小值 print(df.groupby('key1').agg({'data1': 'max', 'data2': 'min'}))
数据合并
数据合并分为两种:拼接(concatenate)、连接(join)数据拼接:
pd.concat([df1,df2]) # 简单把数据拼接
pd.concat([df1,df2],keys=['a','b']) # 把数据表分层,然后拼接
pd.concat([df1,df2], axis=1) # 按行拼接
pd.concat([df1,df2],ignore_index=True)] # 索引要求是唯一
df1.append(df2)
数据连接:
pd.merged(df1,df2,on=字段)
pd.merged(df1,df2,on=[字段1,字段2]
pd.merged(df1,df2,on=字段,how='inner') # how参数可为inner outer left right
时间对象索引处理
这里首先大家要知道有一个可以用来灵活处理时间对象的包:dateutil,这个有什么好呢?不用指定时间格式,如下:import dateutil print(dateutil.parser.parse('2020-01-10')) print(dateutil.parser.parse('2020/01/10')) print(dateutil.parser.parse('2020-JAN-10')) print(dateutil.parser.parse('JAN-10-2020')) # 结果均为2020-01-10 00:00:00,是一个datetime格式
而pandas在此基础上又提供了成组处理时间对象
时间序列的创建
两种创建方法: pd.to_datetime(时间列表字符串):转换成DatetimeIndex pd.date_range,有以下参数: start:开始时间 end:结束时间 periods:时间长度 freq:时间频率,默认为'D',可先H(our) W(eek) Business S(emi-)M(onth) MinT(es) S(econd) A(year) 例如: pd.ta_datetime(start='2018-1-1', periods=10, freq='SM') # 频率为半个月 pd.ta_datetime(start='2018-1-1', periods=10, freq='W-FRI') # 频率为每周五date_times = pd.to_datetime(['2019-12-12', '2020-02-10', '2020-01-30']) print(date_times) # DatetimeIndex(['2019-12-12', '2020-02-10', '2020-01-30'], dtype='datetime64[ns]', freq=None) print(date_times.to_pydatetime()) # 转换成python中的datetime对象
# 创建从2020-01-10到2020-01-20的时间索引 date_times1 = pd.date_range('2020-01-10', end='2020-01-20') # 创建从2020-01-10开始的10天时间索引 date_times2 = pd.date_range('2020-01-10', periods=10) # 创建从2020-01-10开始的10个月时间索引 date_times3 = pd.date_range('2020-01-10', periods=10, freq='M')
DatetimeIndex对象.to_pydatetime():转换成python中的datetime对象