這是很久以前寫的一段代碼,很簡單很基礎。最近突然用到,這裏把它分享出來,希望可以爲有需要的朋友提供幫助。
以及歡迎閱讀這一系列第二篇:地鐵大數據挖掘之客流數據預處理——從原始一卡通數據提取城市地鐵客流(二)
1 解壓文件
這裏以上海城市開放大賽提供的數據爲樣例(提取碼zlsy),需要的朋友可以進行下載。把數據進行解壓後,看到是一個個壓縮文件:
接下來,可以用下面這段代碼對這些數據進行解壓:
import gzip
import os
from datetime import datetime
import shutil
#解壓文件
def un_gz(file_name):
"""ungz zip file"""
f_name = file_name.replace(".gz", "")
#獲取文件的名稱,去掉
g_file = gzip.GzipFile(file_name)
#創建gzip對象
open(f_name, "wb+").write(g_file.read())
#gzip對象用read()打開後,寫入open()建立的文件中。
g_file.close()
#關閉gzip對象
date_l=[datetime.strftime(x,'%Y%m%d') for x in list(pd.date_range('20150401','20150430'))]
file_name=[]
for x in date_l:
filename="SPTCC-"+x+'.csv.gz'
file_name.append(filename)
for each in file_name:
un_gz(each)
#創建文件夾
os.mkdir('railway_data')
#將解壓後的文件移至新文件夾
file_name2=[]
for x in date_l:
filename="SPTCC-"+x+'.csv'
file_name2.append(filename)
for each in file_name2:
shutil.move(each,"railway_data")
2 提取客流
進去新創建的文件夾,可以先看一下數據的樣子:
import pandas as pd
f=open("SPTCC-20150401.csv")
data=pd.read_csv(f,header=0,names=["cardnum","date","time","linename","business","figure","attribute"])
data.head()
這一步我們想得到的結果是某個站點每十分鐘的客流。從“business”字段可以看出,這裏的數據不僅有地鐵的,還有公交等其他數據。而且根據常識,地鐵客流是分進站和出戰的。因此,我們也想分別得到某一時間片內某站的地鐵進站和出站客流。
2.1 提取地鐵數據
剛剛講到,可以通過“business”這一字段判斷是否爲地鐵數據,因此代碼如下:
def railway_data(data):
RailWay=data[data["business"]=="地鐵"]
return RailWay
2.2 劃分相應時間片
這裏用到的字段是“time”。可能會有很方便的做法,如果有更好的方便也歡迎朋友們批評指正。我這裏用到的是一種十分笨的辦法,我把時間看作“六十進制”的數字,對時、分和秒分別乘以3600、60和1,最後獲得一個類似於“時間戳”一樣的數字,再對時間片進行劃分。
#計算“時間戳”
def timespan(data):
data["timespan"]=data["time"].apply(lambda x:x[:2]).astype(int)*3600+data["time"].apply(lambda x:x[3:5]).astype(int)*60+data["time"].apply(lambda x:x[6:]).astype(int)
return data
#劃分時間片
def timebins(data):
#計算每個時間片的秒數間隔
seconds=[600*x for x in range(0,145)]
#給時間片做標籤
label=[x for x in range(1,145)]
#這裏利用的是pandas的分箱操作
_10min=pd.cut(data["timespan"],bins=seconds,labels=label)
_10mins=_10min.get_values()
data['_10mins']=_10mins
return data
2.3 提取進出站客流
這裏利用的是字段“figure"。很明顯,根據日常生活經驗,進站時打卡是不花錢的,出站時根據里程數計費。所以,這裏根據“figure"值是否爲0判斷進出站。
def input_data(data):
inputdata=data[data["figure"]==0]
return inputdata
def output_data(data):
output=data[data["figure"]>0]
return output
2.4 對客流進行統計
之後,對每一個站點的不同時間片客流進行統計:
def groupby_data(data):
grouped_data=data.groupby(["linename","_10mins"]).count()
manageG=grouped_data.reset_index(drop=False)
del grouped_data
gc.collect()
manageG.drop(["cardnum","date","time","business","figure","attribute"],axis=1,inplace=True)
manageG.rename(columns={"timespan":"passengernums"},inplace=True)
return manageG
2.5 融合進出站客流
#mi是進站數據,mo是出站數據
def merge_data(mi,mo):
final_data=pd.merge(mi,mo,how="outer",on=["linename","_10mins"])
final_data.rename(columns={"passengernums_x":"inputnums","passengernums_y":"outputnums"},inplace=True)
FinalData=final_data.fillna(0)
del final_data
gc.collect()
return FinalData
3 整合代碼
最後,把所有的代碼整合在一起,並對一個月30天數據進行處理:
import pandas as pd
from datetime import datetime
import os
#clear memory
import gc
os.mkdir("_10mins")
def open_data(i):
f=open(i)
data=pd.read_csv(f,header=0,names=["cardnum","date","time","linename","business","figure","attribute"])
return data
def railway_data(data):
RailWay=data[data["business"]=="地鐵"]
return RailWay
#計算“時間戳”
def timespan(data):
data["timespan"]=data["time"].apply(lambda x:x[:2]).astype(int)*3600+data["time"].apply(lambda x:x[3:5]).astype(int)*60+data["time"].apply(lambda x:x[6:]).astype(int)
return data
#劃分時間片
def timebins(data):
#計算每個時間片的秒數間隔
seconds=[600*x for x in range(0,145)]
#給時間片做標籤
label=[x for x in range(1,145)]
#這裏利用的是pandas的分箱操作
_10min=pd.cut(data["timespan"],bins=seconds,labels=label)
_10mins=_10min.get_values()
data['_10mins']=_10mins
return data
def input_data(data):
inputdata=data[data["figure"]==0]
return inputdata
def output_data(data):
output=data[data["figure"]>0]
return output
def groupby_data(data):
grouped_data=data.groupby(["linename","_10mins"]).count()
manageG=grouped_data.reset_index(drop=False)
del grouped_data
gc.collect()
manageG.drop(["cardnum","date","time","business","figure","attribute"],axis=1,inplace=True)
manageG.rename(columns={"timespan":"passengernums"},inplace=True)
return manageG
#mi是進站數據,mo是出站數據
def merge_data(mi,mo):
final_data=pd.merge(mi,mo,how="outer",on=["linename","_10mins"])
final_data.rename(columns={"passengernums_x":"inputnums","passengernums_y":"outputnums"},inplace=True)
FinalData=final_data.fillna(0)
del final_data
gc.collect()
return FinalData
date=[datetime.strftime(x,'%Y%m%d') for x in list(pd.date_range('20150401','20150430'))]
for i in date:
filename="SPTCC-"+i+".csv"
SHData=open_data(filename)
RailWay=railway_data(SHData)
del SHData
gc.collect()
TimeSpan_data=timespan(RailWay)
del RailWay
gc.collect()
timebins_data=timebins(TimeSpan_data)
del TimeSpan_data
gc.collect()
inputdata=input_data(timebins_data)
output=output_data(timebins_data)
del timebins_data
gc.collect()
manageinput=groupby_data(inputdata)
manageoutput=groupby_data(output)
del inputdata
gc.collect()
del output
gc.collect()
savedata=merge_data(manageinput,manageoutput)
del manageinput
gc.collect()
del manageoutput
gc.collect()
fn=str(i)+".csv"
path=os.path.join("_10mins",fn)
savedata.to_csv(path)
最後看一下得到的結果:
”_10min“字段代表所處的時間片(比如1代表0:00-0:10),inputnums代表進站客流,outputnums代表出站客流。