Pandas
Pandas 是 Python 的核心数据分析支持库,提供了快速、灵活、明确的数据结构,旨在简单、直观地处理关系型、标记型数据的能力
Pandas中的数据结构
Series
Series是带标签的一维数组,可存储整数、浮点数、字符串、Python 对象等类型的数据。轴标签统称为索引。
s = pd.Series(data, index=index)
data指的是放入其中的数据,index为与data相对的索引。
- 如果data为数组,index的层数必须与data对应。当没有指定index参数的时候,将会创建数值型索引。
- 当只有一个参数data,且data为字典时,将自动生成序列。在py>3.6且pd>0.23时,索引的序列将参照字典的先后顺序,否则将按照字典key的值进行排序。
DataFrame
DataFrame 是由多种类型的列构成的二维标签数据结构,类似于 Excel 、SQL 表,或 Series 对象构成的字典。DataFrame 是最常用的 Pandas 对象,与 Series 一样,DataFrame 支持多种类型的输入数据。
#DataFrame的创建
分组运算
原理:将数据进行分组,组内的计算,并将计算的结果进行合并。
分组运算后,原有的数据格式会被改变。
常用的分组运算函数有:
- transform
- groupBy
#groupy(分组的标准(自定义函数返回值或者series对象或者为数组对象或者map对象)
#groupBy的返回值为dataframe
#按照年份和性别对婴儿姓名数据进行分组
groups = data.groupby(by=['year','gender'])
#查看groups类型
type(groups)
#对df进行'key1','key2'的两次分组,然后取data2的数据,对两次细分的分组数据取均值
value = df.groupby(['key1','key2'])[['data2']].mean()
#通过groupBy进行分组,通过设置可以在任何轴上进行分组
grouped=df.groupby(df.dtypes, axis=1)
#将转换好的dataframe转换为字典
value = dict(list(grouped))
聚合计算
聚合计算的含义为:将所分组的dataFrame进行分组
pandas内置的聚合函数有:
- sum() 求和
- max() 最大值
- min() 最小值
- mean() 平均值
- count() 计数
- std() 平方差
除了内置的函数外,我们也可以使用自定义的函数进行计算。通过agg()方法进行使用。
agg函数中可以使用多个函数进行计算,例如:
dataframe.agg(['std','mean','sum',('自定义函数命名',自定义函数)])
数据导入
索引和列索引的创建
pandas在读取数据时,会进行索引和列名称的创建,默认自动生成行索引,默认第一行为列索引。
#names 表示列索引,index_col表示行索引。
pd.read_scv('ch04/ex2.scv',header = None, names={'a','b','c','d','msg'}, index_col = ['msg'])
消灭不规则的分隔符
在创建dataFrame时,通过正则表达式进行分隔符
#sep为选取分隔符的正则表达式
pd.read_table('exc.scv',sep = '\s+')
指定缺失值
在创建dataFrame时,通过正则表达式进行分隔符
#指定某些值为缺失值
pd.read_csv('exc.scv',na_values={['NA','NULL','foo']})
#指定某一列中的某些值为缺失值
pd.read_csv('exc.scv',na_values={'message':['NA','NULL','foo']})
时间日期的使用
Pandas中 和时间日期相关常用的类以及创建方法。
类 | 备注 | 创建方法 |
---|---|---|
Timestamp | 时刻数据 | to_datetime,Timestamp |
DatetimeIndex | Timestamp的索引 | to_datetime,date_range,DatetimeIndex |
Period | 时期数据 | Period |
PeriodIndex | Period | period_range, PeriodIndex |
pd.Timestamp(2018,5,21)
Out[12]: Timestamp('2018-05-21 00:00:00')
pd.Timestamp('2018-5-21')
Out[13]: Timestamp('2018-05-21 00:00:00')
#除了时间戳之外,另一个常见的结构是时间跨度(Period)。
pd.Period("2018-01")
Out[14]: Period('2018-01', 'M')
pd.Period("2018-05", freq="D")
Out[15]: Period('2018-05-01', 'D')
#索引后会自动强制转为为 DatetimeIndex 和 PeriodIndex。
dates = [pd.Timestamp("2018-05-01"), pd.Timestamp("2018-05-02"), pd.Timestamp("2018-05-03"), pd.Timestamp("2018-05-04")]
ts = pd.Series(data=["Tom", "Bob", "Mary", "James"], index=dates)
ts.index
Out[16]: DatetimeIndex(['2018-05-01', '2018-05-02', '2018-05-03', '2018-05-04'], dtype='datetime64[ns]', freq=None)
periods = [pd.Period("2018-01"), pd.Period("2018-02"), pd.Period("2018-03"), pd.Period("2018-4")]
ts = pd.Series(data=["Tom", "Bob", "Mary", "James"], index=periods)
ts.index
Out[17]: PeriodIndex(['2018-01', '2018-02', '2018-03', '2018-04'], dtype='period[M]', freq='M')
将文本转化为时间戳
可以通过to_datatime的方法快速将字符串转换为时间戳。当传递一个Series的时候会返回一个Series
pd.to_datetime(pd.Series(["Jul 31, 2018", "2018-05-10", None]))
Out[18]:
0 2018-07-31
1 2018-05-10
2 NaT
dtype: datetime64[ns]
pd.to_datetime(["2005/11/23", "2010.12.31"])
Out[19]: DatetimeIndex(['2005-11-23', '2010-12-31'], dtype='datetime64[ns]', freq=None)
#除了可以将文本数据转为时间戳外,还可以将 unix 时间转为时间戳。
pd.to_datetime([1349720105, 1349806505, 1349892905], unit="s")
Out[20]:
DatetimeIndex(['2012-10-08 18:15:05', '2012-10-09 18:15:05',
'2012-10-10 18:15:05'],
dtype='datetime64[ns]', freq=None)
pd.to_datetime([1349720105100, 1349720105200, 1349720105300], unit="ms")
Out[21]:
DatetimeIndex(['2012-10-08 18:15:05.100000', '2012-10-08 18:15:05.200000',
'2012-10-08 18:15:05.300000'],
dtype='datetime64[ns]', freq=None)
生成时间戳范围
为了方便的生成 某个范围内的时间戳,可以使用date_range和bdate_range来完成时间戳范围的生成。其返回的对象为DatetimeIndex类
pd.date_range("2018-6-26", periods=8)
Out[22]:
DatetimeIndex(['2018-06-26', '2018-06-27', '2018-06-28', '2018-06-29',
'2018-06-30', '2018-07-01', '2018-07-02', '2018-07-03'],
dtype='datetime64[ns]', freq='D')
pd.bdate_range("2018-6-26", periods=8)
Out[23]:
DatetimeIndex(['2018-06-26', '2018-06-27', '2018-06-28', '2018-06-29',
'2018-07-02', '2018-07-03', '2018-07-04', '2018-07-05'],
dtype='datetime64[ns]', freq='B')
#可以看出,date_range 默认使用的频率是 日历日,而 bdate_range 默认使用的频率是 营业日。当然了,我们可以自己指定频率,比如,我们可以按周来生成时间戳范围。
pd.date_range("2018-6-26", periods=8, freq="W")
Out[24]:
DatetimeIndex(['2018-07-01', '2018-07-08', '2018-07-15', '2018-07-22',
'2018-07-29', '2018-08-05', '2018-08-12', '2018-08-19'],
dtype='datetime64[ns]', freq='W-SUN')
时间序列的相关方法
在做时间序列相关的工作时,经常要对时间做一些移动/滞后、频率转换、采样等相关操作。
(1)移动
shift方法,移动时间序列。可以通过freq指定移动的时长
ts.shift(2)
Out[36]:
2018-06-24 NaN
2018-07-01 NaN
2018-07-08 0.0
2018-07-15 1.0
Freq: W-SUN, dtype: float64
ts.shift(2, freq=Day())
Out[37]:
2018-06-26 0
2018-07-03 1
2018-07-10 2
2018-07-17 3
Freq: W-TUE, dtype: int64
#可以看到,现在日期索引移动了 2 天的间隔。通过 tshift 同样可以达到相同的效果。
ts.tshift(2, freq=Day())
Out[38]:
2018-06-26 0
2018-07-03 1
2018-07-10 2
2018-07-17 3
Freq: W-TUE, dtype: int64
(2)重采样
resample 表示根据日期维度进行数据聚合,可以按照分钟、小时、工作日、周、月、年等来作为日期维度,更多的日期维度见 Offset
# 求出每个月的数值之和
ts.resample("1M").sum()
Out[41]:
2018-06-30 0
2018-07-31 6
Freq: M, dtype: int64
# 求出每个月的数值平均值
ts.resample("1M").mean()
Out[42]:
2018-06-30 0
2018-07-31 2
Freq: M, dtype: int64