俗话说的好数据预处理真是要花费70%的时间,这次的数据有40多w条,原来是卫星数据,老师已经处理成csv了,减少了很多工作量。
数据是这样的,时间线补全,多个变量。
citycode为城市代码
首先,为数据分类,按城市、时间排序
# 数据分类
# 按城市排序,按时间排序
others_var.sort_values(by=['citycode','year','month','day','hour'], ascending=True,inplace=True)
查看各城市样本点个数
# 计算各市数据点个数
# 375张家界 365岳阳 389株洲 34常德 326湘潭 38长沙 327湘西
# 111衡阳 42郴州 360永州 254邵阳 118怀化 356益阳 191娄底
pd.value_counts(others_var.iloc[:,1])
由于各个城市的时间长短不同,缺失也不同,所以先分类,按城市处理。
# 按地区划分数据
# 长沙:2014/5/13-2018/4/30 32585条
# 株洲:2014/5/13-2018/4/30 32766条
# 湘潭:2014/5/13-2018/4/30 32702条
# 岳阳:2014/5/13-2018/4/30 32806条
# 衡阳:2015/1/2-2018/4/30 27803条
# 郴州:2015/1/2-2018/4/30 27779条
# 永州:2015/1/2-2018/4/30 27775条
# 娄底:2015/1/2-2018/4/30 27529条
# 邵阳:2015/1/2-2018/4/30 27774条
# 常德:2014/5/13-2018/4/30 32749条
# 益阳:2015/1/2-2018/4/30 27688条
# 张家界:2014/5/13-2018/4/30 32842条
# 怀化:2015/1/2-2018/4/30 27769条
# 湘西:2015/1/2-2018/4/30 27813条
others_var_cs=others_var[others_var['citycode'].isin([38])] #长沙
others_var_zz=others_var[others_var['citycode'].isin([389])] #株洲
others_var_xt=others_var[others_var['citycode'].isin([326])] #湘潭
others_var_yy=others_var[others_var['citycode'].isin([365])] #岳阳
others_var_hy=others_var[others_var['citycode'].isin([111])] #衡阳
others_var_cz=others_var[others_var['citycode'].isin([42])] #郴州
others_var_yz=others_var[others_var['citycode'].isin([360])] #永州
others_var_ld=others_var[others_var['citycode'].isin([191])] #娄底
others_var_sy=others_var[others_var['citycode'].isin([254])] #邵阳
others_var_cd=others_var[others_var['citycode'].isin([34])] #常德
others_var_yiy=others_var[others_var['citycode'].isin([356])] #益阳
others_var_zjj=others_var[others_var['citycode'].isin([375])] #张家界
others_var_hh=others_var[others_var['citycode'].isin([118])] #怀化
others_var_xx=others_var[others_var['citycode'].isin([327])] #湘西
预处理思路如下:
step1 补全时间线:利用start、end时间创造时间,然后遍历 如有缺失存储为nan
step2 补全缺失值:利用时间序列方法,连续变量使用线性插值(因为这里缺失并不多,用什么插值都行),离散变量(这里是vacation,01变量,一天中要么全是0要么全是1)使用升采样和降采样,先计算一天的总和,一天中只要存在1那么就都是1.这里要注意的是升采样和降采样可能会变动你的时间序列,所以要进行补全。
#补全缺失时间
#利用线性补全连续变量
#利用升采样降采样补全离散变量(只有一个离散变量01,vacation)
import datetime
def complete(data):
# 提取时间
date=pd.to_datetime(data['datamdy']) # 将日期转化为Timestamp
hour=np.array(data['hour']) # 将时间转化为array
trans_time=[]
for i in range(date.shape[0]):
time=np.array(date)[i]+pd.Timedelta(hour[i],'h')+pd.Timedelta('30m')
trans_time.append(time)
# 提取时间 将hour变量更改为时间
time=trans_time
data['hour']=time
data=data.iloc[:,6:] #切块后只剩下时间和变量
#补全时间线
date_start = data['hour'].min()
date_end = data['hour'].max()
for i in range(0,((date_end-date_start).days+1)*24-1):
date=(date_start+datetime.timedelta(hours=i))
if (date not in data['hour'].values):
new_date=pd.DataFrame(data={'hour':date,'value':-1},index=[data.shape[0]]) #缺失时间是整行为nan
data=data.append(new_date,ignore_index=True)
data=data.sort_values('hour').reset_index(drop=True)
print('缺失值个数:{0}'.format( pd.value_counts(data.iloc[:,-1])))
#开始处理缺失值
#连续变量用线性插值补全
#离散变量只有vacation i=6
index=pd.date_range(date_start,date_end,freq='h')
for i in range(data.shape[1]-2):
var=pd.Series(np.array(data.iloc[:,i+1]),index=index)
# 离散变量
# 由于vacation为01变量,要么全天都为1要么全天都为0
if i== 6: #vacation
var=var.resample('d').sum()
for j in range(len(var)):
if var[j]>0:
var[j]=1
var=var.resample('h').ffill()
temp_var=pd.Series(np.nan,pd.date_range('2018-4-30 1:00',periods=23,freq='h')) #升采样后最后一个值为2018-4-30 0:00 所以需要补全
var=var.append(temp_var).ffill()
# 从2015/1/2开始的数据是从1点开始的 没有0点数据 而降采样之后多出了一个0点
if len(var)<30000:
var=var.truncate(before = '2015-1-2 1:00')
# 连续变量
else:
var=var.interpolate('linear')
data.iloc[:,i+1]=np.array(var)
data=data.drop(['value'],axis=1)
return data
这40w条数据足足跑了3分多钟。。。深感电脑不行!不过函数也粗糙了。。。