今天记一下处理数据中发现的pandas的好功能
1、explode ->拆分数据为多行
我们遇到的车辆轨迹数据是这样的,第一列是车辆的id,第二列是该车辆的轨迹信息,包括时间,经度,纬度
我们现在想做的是将最后一列按照第一列car_id拆分为多行,即下图所示 ,这样才方便进行后续处理
最早我是拿循环加嵌套列表完成转换的,后来发现pandas有explode这个函数,简单来说,就是把datafrmae某一列中嵌套的列表拆分为多行数据
import pandas as pd
data=pd.read_csv('tra_data.csv')
data['tra_info']=data['tra_info'].apply(eval)
导入数据并把轨迹列由字符串变为列表类型
data=data.explode('tra_info')
可以看到执行explode后已经拆分为了多行数据
data['time']=data.apply(lambda x :x.tra_info[0],axis=1)
data['lon']=data.apply(lambda x :x.tra_info[1],axis=1)
data['lat']=data.apply(lambda x :x.tra_info[2],axis=1)
data=data.drop(['tra_info'],axis=1)
把拆开的列表利用apply函数进一步分为多列:
更多见官方文档:
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.explode.html
2、resample ->对时间序列重采样
现在继续利用上面处理过的的轨迹数据,按照5min统计车辆订单时间分布
这个时候就用到了resample
把日期列由字符串转换为时间类型:
resample_data=order_data.resample('5T',on='time').agg({"lon":'count'})
利用resample对时间序列数据重采样(5T代表5min为间隔):
季度是Q、月度是M、星期是W、N天是ND,时是H、分是T、秒是S
如5T代表5min,10S代表10秒,
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.resample.html
可以看到第一列都变为了以5min为时间间隔的时刻
resample_data=resample_data.reset_index(drop=False)
#改变日期格式
resample_data['time_noday'] =resample_data['time'].apply(lambda x: x.strftime('%H:%M'))
新建一列只保存时间,去除日期,以便分组统计订单:
result=resample_data.groupby(['time_noday'],as_index=False).agg({"lon":'mean'})
分组统计每个时刻的订单量:
# 画图
times=result['time_noday'].tolist()
# 分时间区间,保证最后一位纳入标签
ticks=list(range(0,len(times),4))
if ticks[-1]!=len(times)-1:ticks.append(len(times)-1)
labels=[times[i] for i in ticks]
# bbox_props = dict(boxstyle="round", fc="w", ec="0.5", alpha=0)
mpl.rcParams['font.sans-serif'] = ['Times New Roman']
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
fig= plt.figure(figsize=(8, 4),dpi=100)
ax1 = fig.add_subplot(111)
ax1.plot(result['lon'],'-',linewidth=1)
# ax1.legend(loc='best', frameon=False,fontsize = 10)
ax1.set_xlabel('Time',fontsize =10)
ax1.set_ylabel('Orders',fontsize =10)
ax1.set(xlim=[0,len(times)-1])
ax1.set_xticks(ticks)
ax1.set_xticklabels(labels, rotation=45, horizontalalignment='right')
ax1.tick_params(labelsize=6)
ax1.set_title('Time distribute',fontsize =8)
plt.savefig('time_distribute_5min.png',format='png', dpi=300)
plt.show()
画出来轨迹订单5min采样的时间分布
改一下参数很容易得到
15min采样的时间分布
1h采样的时间分布