学习参考:https://github.com/datawhalechina/joyful-pandas
Ex1:太阳辐射数据集
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
现有一份关于太阳辐射的数据集:
df = pd.read_csv('../data/solar.csv', usecols=['Data','Time','Radiation','Temperature'])
df.head(3)
- 将
Date, Time
合并为一个时间列Datetime
,同时把它作为索引后排序。 - 每条记录时间的间隔显然并不一致,请解决如下问题:
- 找出间隔时间的前三个最大值所对应的三组时间戳。
- 是否存在一个大致的范围,使得绝大多数的间隔时间都落在这个区间中?如果存在,请对此范围内的样本间隔秒数画出柱状图,设置
bins=50
。
- 求如下指标对应的
Series
:
- 温度与辐射量的6小时滑动相关系数
- 以三点、九点、十五点、二十一点为分割,该观测所在时间区间的温度均值序列
- 每个观测6小时前的辐射量(一般而言不会恰好取到,此时取最近时间戳对应的辐射量)
#1.将Datetime, Time合并为一个时间列Datetime,同时把它作为索引后排序。
solar_date = df.Data.str.extract(r'([/\w]+\s).+')[0]
solar_date.head()
df['Data'] = pd.to_datetime(solar_date + df.Time) # 两列字符连接
df = df.drop(columns='Time').rename(columns={'Data':'Datetime'}).set_index('Datetime').sort_index()
df.head()
#2.找出间隔时间的前三个最大值所对应的三组时间戳
s = df.index.to_series().reset_index(drop=True)
s
diff_s = s.diff().dt.total_seconds() # 间隔时间
diff_s
max_3 = diff_s.nlargest(3).index # 间隔时间的前三个最大值对应的索引
max_3
max_3.union(max_3-1) # 对应原表的索引
df.index[max_3.union(max_3-1)]
#3.是否存在一个大致的范围,使得绝大多数的间隔时间都落在这个区间中?如果存在,请对此范围内的样本间隔秒数画出柱状图,设置bins=50。
res = diff_s.mask((diff_s>diff_s.quantile(0.99))|(diff_s<diff_s.quantile(0.01))) # 时间间隔数值落在quantile(0.01-0.99)之间
_ = plt.hist(res, bins=50)
#4.温度与辐射量的6小时滑动相关系数
res = df.Radiation.rolling('6H').corr(df.Temperature)
res.tail()
#5.以三点、九点、十五点、二十一点为分割,该观测所在时间区间的温度均值序列
res = df.Temperature.resample('6H', origin='03:00:00').mean()
res.head() # 从前一天的21点开始计算
#6.每个观测6小时前的辐射量(取最近时间戳对应的辐射量)
my_dt = df.index.shift(freq='-6H')
my_dt[:5]
int_loc = [df.index.get_loc(i, method='nearest') for i in my_dt] # my_dt数组中的datatime在df数据框的索引
int_loc[:5]
res = df.Radiation.iloc[int_loc]
res.head()
Ex2:水果销量数据集
现有一份2019年每日水果销量记录表:
df = pd.read_csv('../data/fruit.csv')
df.head(3)
- 统计如下指标:
- 每月上半月(15号及之前)与下半月葡萄销量的比值
- 每月最后一天的生梨销量总和
- 每月最后一天工作日的生梨销量总和
- 每月最后五天的苹果销量均值
- 按月计算周一至周日各品种水果的平均记录条数,行索引外层为水果名称,内层为月份,列索引为星期。
- 按天计算向前10个工作日窗口的苹果销量均值序列,非工作日的值用上一个工作日的结果填充。
#1.每月上半月(15号及之前)与下半月葡萄销量的比值
df.Date = pd.to_datetime(df.Date)
df_grape = df.query("Fruit == 'Grape'")
df_grape.head()
np.where(df_grape.Date.dt.day<=15,'First', 'Second') # 使用'First','Second'分别替代上半月和下半月的日期
res = df_grape.groupby([np.where(df_grape.Date.dt.day<=15,'First', 'Second'),df_grape.Date.dt.month])['Sale'].mean().to_frame() # 每月上半月和下半月葡萄销量
res.head()
res = res.unstack(0).droplevel(0,axis=1) # 去除外层索引
res.head()
res = (res.First/res.Second).rename_axis('Month')
res.head()
#2.每月最后一天的生梨销量总和
pear_df = df[df.Date.dt.is_month_end].query("Fruit == 'Pear'")
pear_df.head()
pear_df.groupby('Date')['Sale'].sum()
#3.每月最后一天工作日的生梨销量总和
workday_array = pd.date_range('20190101', '20191231',freq='BM') # 每月最后一个工作日
workday_array[:5]
pear_df = df[df.Date.isin(workday_array)].query("Fruit == 'Pear'")
pear_df.head()
pear_df.groupby('Date').Sale.mean().head()
#4.每月最后五天的苹果销量均值
target_dt = df.drop_duplicates().groupby(df.Date.drop_duplicates().dt.month)['Date'].nlargest(5).reset_index(drop=True) # 每个月最后五天
target_dt.head()
res = df.set_index('Date').loc[target_dt].reset_index().query("Fruit == 'Apple'") # 每个月最后五天苹果销量
res.head()
res = res.groupby(res.Date.dt.month)['Sale'].mean().rename_axis('Month')
res
#4.按月计算周一至周日各品种水果的平均记录条数,行索引外层为水果名称,内层为月份,列索引为星期。
month_order = ['January','February','March','April',
'May','June','July','August','September',
'October','November','December']
week_order = ['Mon','Tue','Wed','Thu','Fri','Sat','Sum']
group1 = df.Date.dt.month_name().astype('category').cat.reorder_categories(month_order, ordered=True) # df数据月份替换为英文名
group1.head()
group2 = df.Fruit
group3 = df.Date.dt.dayofweek.replace(dict(zip(range(7),week_order))
).astype('category').cat.reorder_categories(week_order, ordered=True) # df数据日期按照周一至周日进行替换
group3.head()
res = df.groupby([group1, group2,group3])['Sale'].count().to_frame()
res.head()
res = res.unstack(0).droplevel(0,axis=1)
res.head()
#5.按天计算向前10个工作日窗口的苹果销量均值序列,非工作日的值用上一个工作日的结果填充。
df_apple = df[(df.Fruit=='Apple')&(~df.Date.dt.dayofweek.isin([5,6]))] # 工作日苹果的销量
df_apple.head()
s = pd.Series(df_apple.Sale.values,index=df_apple.Date).groupby('Date').sum() # 工作日苹果的销量
s.head()
res = s.rolling('10D').mean().reindex(pd.date_range('20190101','20191231')).fillna(method='ffill') #前10个工作日窗口的苹果销量均值
res.head()