当前位置: 代码迷 >> 综合 >> pandas之explode、resample
  详细解决方案

pandas之explode、resample

热度:0   发布时间:2023-12-18 04:58:06.0

今天记一下处理数据中发现的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采样的时间分布

  相关解决方案