时间序列数据处理
to_datetime
与 dt.strftime
实际工作中,经常会遇到大量的时间序列数据。这些时间序列的原始数据一般为文本格式,我们需要将它转化为时间日期格式。 Pandas 提供了 to_datetime
函数将其他日期时间格式转化为 Python 的日期时间格式。例如:
import pandas as pd
pd.to_datetime('20200514')
Timestamp('2020-05-14 00:00:00')
pd.to_datetime('2020/05/14')
Timestamp('2020-05-14 00:00:00')
pd.to_datetime('2020-05-14')
Timestamp('2020-05-14 00:00:00')
在上面的代码中可以看出,to_datetime
方法将不同类型的时间数据字符串转化为 Timestamp 格式:年-月-日 时:分:秒
。另外一个函数dt.strftime
可以将 Pandas 的 Timestamp 格式数据转化为其他格式的字符串,例如:
df = pd.DataFrame({'入校时间': ['2016-09-15', '2017-03-23', '2018-09-05'], '统计学': [85, 68, 90], '高数': [82, 63, 88], '英语': [84, 90, 78], '姓名': ['张三', '李四', '王五']})
df
| 入校时间 | 统计学 | 高数 | 英语 | 姓名 |
---|
0 | 2016-09-15 | 85 | 82 | 84 | 张三 |
---|
1 | 2017-03-23 | 68 | 63 | 90 | 李四 |
---|
2 | 2018-09-05 | 90 | 88 | 78 | 王五 |
---|
df.iloc[0, 0]
'2016-09-15'
df['入校时间'] = pd.to_datetime(df['入校时间'])
df
| 入校时间 | 统计学 | 高数 | 英语 | 姓名 |
---|
0 | 2016-09-15 | 85 | 82 | 84 | 张三 |
---|
1 | 2017-03-23 | 68 | 63 | 90 | 李四 |
---|
2 | 2018-09-05 | 90 | 88 | 78 | 王五 |
---|
df.iloc[0, 0]
Timestamp('2016-09-15 00:00:00')
df['入校时间'].dt.strftime('%m-%d-%y')
0 09-15-16
1 03-23-17
2 09-05-18
Name: 入校时间, dtype: object
df['入校时间'].dt.strftime('%B-%d-%y')
0 September-15-16
1 March-23-17
2 September-05-18
Name: 入校时间, dtype: object
df['入校时间'].dt.strftime('%B-%d-%Y')
0 September-15-2016
1 March-23-2017
2 September-05-2018
Name: 入校时间, dtype: object
df['入校时间'].dt.strftime('%Y-%W')
0 2016-37
1 2017-12
2 2018-36
Name: 入校时间, dtype: object
df['入校时间'].dt.strftime('%Y-%m-%w')
0 2016-09-4
1 2017-03-4
2 2018-09-3
Name: 入校时间, dtype: object
数据聚合函数resample
对于很多时间序列数据,有时候经常需要对它们按一定周期进行数据聚合,可以用 Pandas 提供的resample
函数。resample 方法中的小括号中用不同参数表示聚合的频率。举例:
import numpy as np
index = pd.date_range('12/24/2019', periods = 10, freq ='D')
index
DatetimeIndex(['2019-12-24', '2019-12-25', '2019-12-26', '2019-12-27',
'2019-12-28', '2019-12-29', '2019-12-30', '2019-12-31',
'2020-01-01', '2020-01-02'],
dtype='datetime64[ns]', freq='D')
df = pd.DataFrame(np.arange(10),index = index)
df
| 0 |
---|
2019-12-24 | 0 |
---|
2019-12-25 | 1 |
---|
2019-12-26 | 2 |
---|
2019-12-27 | 3 |
---|
2019-12-28 | 4 |
---|
2019-12-29 | 5 |
---|
2019-12-30 | 6 |
---|
2019-12-31 | 7 |
---|
2020-01-01 | 8 |
---|
2020-01-02 | 9 |
---|
df.resample('M').sum()
| 0 |
---|
2019-12-31 | 28 |
---|
2020-01-31 | 17 |
---|
df.resample('3D').sum()
| 0 |
---|
2019-12-24 | 3 |
---|
2019-12-27 | 12 |
---|
2019-12-30 | 21 |
---|
2020-01-02 | 9 |
---|
df.resample('w').sum()
| 0 |
---|
2019-12-29 | 15 |
---|
2020-01-05 | 30 |
---|
resample
的其他参数中, ‘T’ 表示分钟,‘H’ 表示小时,除了跟sum()
方法外,还可以跟asfreq()
,ffill
,apply()
等。
数据清洗
数据替换replace
, fillna
在进行数据处理时,经常需要对原始数据的一些异常值或错误值进行批量处理。 Pandas 提供了replace
函数方便地进行这项操作。replace
函数第一项为原数据中的值,第二项为需要替换的值。例如,有下面的学生成绩:
import pandas as pd
import numpy as np
df = pd.DataFrame(np.array([[85, 68, 90], [82, 63, 88], [84, 90, 78]]), columns=['统计学', '高数', '英语'], index=['张三', '李四', '王五'])
df
| 统计学 | 高数 | 英语 |
---|
张三 | 85 | 68 | 90 |
---|
李四 | 82 | 63 | 88 |
---|
王五 | 84 | 90 | 78 |
---|
将其中的分数 90 替换为缺失值 NaN,注意,replace
返回了一个新的数据,但原始数据并没有改变。
df.replace(90, np.nan)
| 统计学 | 高数 | 英语 |
---|
张三 | 85 | 68 | 85 |
---|
李四 | 82 | 63 | 88 |
---|
王五 | 84 | 85 | 78 |
---|
df
| 统计学 | 高数 | 英语 |
---|
张三 | 85 | 68 | 90 |
---|
李四 | 82 | 63 | 88 |
---|
王五 | 84 | 90 | 78 |
---|
若需要原始数据改变,需要跟上参数inplace = True
,下面讲到的函数fillna
、drop_duplicates
、dropna
、 rename
等也可以跟这个参数将原始数据改变。
df.replace(90, np.nan, inplace = True)
df
| 统计学 | 高数 | 英语 |
---|
张三 | 85 | 68.0 | NaN |
---|
李四 | 82 | 63.0 | 88.0 |
---|
王五 | 84 | NaN | 78.0 |
---|
Pandas 提供fillna
函数批量替换数据表中的缺失值 NaN。例如:
df.fillna(80)
| 统计学 | 高数 | 英语 |
---|
张三 | 85 | 68.0 | 80.0 |
---|
李四 | 82 | 63.0 | 88.0 |
---|
王五 | 84 | 80.0 | 78.0 |
---|
df.fillna('missing')
| 统计学 | 高数 | 英语 |
---|
张三 | 85 | 68.0 | missing |
---|
李四 | 82 | 63.0 | 88.0 |
---|
王五 | 84 | missing | 78.0 |
---|
Pandas 还可以直接调用isnull
函数判断数据是否为缺失值:
df['英语'].isnull()
张三 True
李四 False
王五 False
Name: 英语, dtype: bool
重复值处理drop_duplicates
在数据量比较大时,经常会遇到重复数据的问题,可以使用函数drop_duplicates
将重复数据去掉。例如:
df = pd.DataFrame([['一班', '男', 85, 68, 90], ['一班', '男', 85, 68, 90], ['二班', '女',84, 90, 78], ['三班', '女',75, 68, 80],\
['二班', '女',69, 55, 63], ['一班', '男', 89, 95, 93]], columns=['班级','性别','统计学','高数','英语'],\
index=['张三', '张三', '王五', '马六', '陈小虎', '魏大帅'])
df
| 班级 | 性别 | 统计学 | 高数 | 英语 |
---|
张三 | 一班 | 男 | 85 | 68 | 90 |
---|
张三 | 一班 | 男 | 85 | 68 | 90 |
---|
王五 | 二班 | 女 | 84 | 90 | 78 |
---|
马六 | 三班 | 女 | 75 | 68 | 80 |
---|
陈小虎 | 二班 | 女 | 69 | 55 | 63 |
---|
魏大帅 | 一班 | 男 | 89 | 95 | 93 |
---|
前两行的数据完全相同,使用函数drop_duplicates
处理:
df.drop_duplicates()
| 班级 | 性别 | 统计学 | 高数 | 英语 |
---|
张三 | 一班 | 男 | 85 | 68 | 90 |
---|
王五 | 二班 | 女 | 84 | 90 | 78 |
---|
马六 | 三班 | 女 | 75 | 68 | 80 |
---|
陈小虎 | 二班 | 女 | 69 | 55 | 63 |
---|
魏大帅 | 一班 | 男 | 89 | 95 | 93 |
---|
缺失值处理drop_na
dropna
函数可以将数据表中包含缺失值的行去除掉,与drop_duplicates
相比,该方法的可调节参数更多些。它的语法如下:
DataFrame.dropna(axis=0, how='any', thresh=None, inplace=False)} |
---|
axis | axis=0 表示删除含空值所在行,axis=1 表示删除含空值所在列 |
how | 默认为 how='any',表示若有空值,就删除 |
how='all',表示全部是空值才删除该行或该列 |
thresh | 空值的个数,作为行或列的删除标准 |
inplace | 若 inplace=True,表示处理后的数据替换原数据 |
df = pd.DataFrame({'统计学': [85, 68, np.nan], '高数': [82, 75, 88], '英语': [np.nan, 90, 78]}, index=['张三', '李四', '王五'])
df
| 统计学 | 高数 | 英语 |
---|
张三 | 85.0 | 82 | NaN |
---|
李四 | 68.0 | 75 | 90.0 |
---|
王五 | NaN | 88 | 78.0 |
---|
df.dropna()
df.dropna(axis = 1)
df.dropna(how = 'all')
| 统计学 | 高数 | 英语 |
---|
张三 | 85.0 | 82 | NaN |
---|
李四 | 68.0 | 75 | 90.0 |
---|
王五 | NaN | 88 | 78.0 |
---|
重命名rename
在处理数据表时,有时候要给数据的行名或列名重命名,此时要用到rename
函数,rename
函数中的参数为一个字典形式:替换前的名字为字典的 key,替换后的名字为字典的 value。
df = pd.DataFrame({'统计学': [85, 68, 90], '高数': [82, 63, 88], '英语': [84, 90, 78]})
df
| 统计学 | 高数 | 英语 |
---|
0 | 85 | 82 | 84 |
---|
1 | 68 | 63 | 90 |
---|
2 | 90 | 88 | 78 |
---|
df.rename(columns = {'统计学': '科目A', '高数': '科目B'})
| 科目A | 科目B | 英语 |
---|
0 | 85 | 82 | 84 |
---|
1 | 68 | 63 | 90 |
---|
2 | 90 | 88 | 78 |
---|