利用pandas按日期做分組運算的操作

原始數據

TS PERIOD REQUEST STEPPED VALUE STATUS SECONDS
20-DEC-16 00:00:00.0 600 1 0  2.018 0 1482163200
20-DEC-16 00:01:00.0 600 1 0  2.019 0 1482163260
20-DEC-16 00:02:00.0 600 1 0  2.019 0 1482163320
20-DEC-16 00:03:00.0 600 1 0  2.019 0 1482163380
20-DEC-16 00:04:00.0 600 1 0  2.019 0 1482163440
20-DEC-16 00:05:00.0 600 1 0  2.020 0 1482163500
20-DEC-16 00:06:00.0 600 1 0  2.020 0 1482163560

我們的目標是把TS列從

20-DEC-16 00:00:00.0

轉變為

20-DEC-16

的格式,然後按天取均值。

導入包

import numpy as np
from pandas import DataFrame, Series
import pandas as pd
from datetime import datetime

讀入文件

df = pd.read_csv('data/test.txt',sep='\t')

這裡沒有解決中文路徑名和絕對路徑的問題.

轉化為數據框

df = DataFrame(df)

轉化為時間格式

將TS列轉化為時間格式,並保存為新的一列DATE,之後,隻留下DATE和VALUE兩列,其他統統不要。

df['DATE'] = pd.to_datetime(df['TS'])
df = df[['DATE','VALUE']]

關鍵一步

把形如‘2017-9-4 00:00:00’轉化為‘2017-9-4 ‘

df['DATE'] = [datetime.strftime(x,'%Y-%m-%d') for x in df['DATE']]

strftime有若幹參數,其中Y表示四位數的年,m表示兩位數的月。

旋轉數據框

df =df.pivot_table(index='DATE',aggfunc='mean')

補充:利用Pandas和Numpy按時間戳將數據以Groupby方式分組

首先說一下需求,我需要將數據以分鐘為單位進行分組,然後每一分鐘內的數據作為一行輸出,因為不同時間的數據量不一樣,所以所有數據按照最長的那組數據為準,不足的數據以各自的最後一個數據進行補足。

之後要介紹一下我的數據源,之前沒用的數據列已經去除,我隻留下要用到的數據data列和時間戳time列,時間戳是以秒計的,可以看到一共是407454行。


   data   time
0  6522.50 1.530668e+09
1  6522.66 1.530668e+09
2  6523.79 1.530668e+09
3  6523.79 1.530668e+09
4  6524.82 1.530668e+09
5  6524.35 1.530668e+09
6  6523.66 1.530668e+09
7  6522.64 1.530668e+09
8  6523.25 1.530668e+09
9  6523.88 1.530668e+09
10  6525.30 1.530668e+09
11  6525.70 1.530668e+09
...   ...   ...
407443 6310.69 1.531302e+09
407444 6310.55 1.531302e+09
407445 6310.42 1.531302e+09
407446 6310.40 1.531302e+09
407447 6314.03 1.531302e+09
407448 6314.04 1.531302e+09
407449 6312.84 1.531302e+09
407450 6312.57 1.531302e+09
407451 6312.56 1.531302e+09
407452 6314.04 1.531302e+09
407453 6314.04 1.531302e+09
 
[407454 rows x 2 columns]

開始進行數據處理,定義一個函數,輸入為一個DataFrame和時間列的命名。

def getdata_time(dataframe,name):
 dataframe[name] = dataframe[name]/60 #將時間轉換為分鐘
 dataframe[name] = dataframe[name].astype('int64') 
 datalen = dataframe.groupby(name).count().max()  #獲取數據最大長度 
 timeframe = dataframe.groupby(name).count().reset_index()#為瞭獲取時間將分組後時間轉換為DataFrame
 timeseries = timeframe['time'] 
 array = []  #建立一個空數組以便存值

 for time, group in dataframe.groupby(name): 
 tmparray = numpy.array(group['data']) #將series轉換為數組並添加到總數組中
 array.append(tmparray) 
 notimedata = pandas.DataFrame(array)
 notimedata = notimedata.fillna(method='ffill',axis = 1,limit=datalen[0]) #將缺失值補全
 notimedata[datalen[0]+1] = timeseries #把時間添加到最後一列 
 return notimedata

下面將逐行進行分析,首先要以每分鐘為依據進行分組,那麼將秒計的時間戳除以60變為分鐘,轉換為int型是為瞭觀察方便(更改類型是否會導致數據精度缺失影響結果並不清楚,如果有瞭解的人看到歡迎指出,謝謝)。

datalen是我們要用到的每分鐘中最大的數據長度,用來作為標齊依據。DataFrame.groupby.count()是分別顯示每組數據的個數,並不是顯示有多少個分組,如果想要獲取分組後每一組的index就需要用到下一行的reset_index方法,之所以不直接用reset_index而是在count()方法後調用是因為groupby分組後的結果不是一個DataFrame,而經過count()(不僅僅是count,對分組數據操作的方法都可以,隻要得出的結果是與每一組的index一一對應即可)操作後就可以得到一個以index為一列,另一列是count結果的DataFrame。

以下為直接進行reset_index操作的報錯:

AttributeError: Cannot access callable attribute 'reset_index' of 'DataFrameGroupBy' objects, try using the 'apply' method

以下為經過count操作後的reset_index方法顯示結果,可以看到一共分為瞭10397組:

   time data
0  25511135 33
1  25511136 18
2  25511137 25
3  25511138 42
4  25511139 36
5  25511140  7
6  25511141 61
7  25511142 45
8  25511143 46
9  25511144 19
10  25511145 21
...   ... ...
10387 25521697  3
10388 25521698  9
10389 25521699 16
10390 25521700 13
10391 25521701  4
10392 25521702 34
10393 25521703 124
10394 25521704 302
10395 25521705 86
10396 25521706 52
 
[10397 rows x 2 columns]

提取的timeseries將在最後數據整合時使用。

現在開始將每組數據提取,首先建立一個空的數組用來存放,然後利用for循環獲取每一組的信息,time即為分組的index,group即為每一分組的內容,將數據從group[‘data’]中取出並添加到之前建立的空數組裡,循環操作過後轉換為DataFrame,當然這個DataFrame中包含瞭大量缺失值,因為它的列數是以最長的數據為準。

如下:

   0  1  2  3  ... 1143 1144 1145 1146
0  6522.50 6522.66 6523.79 6523.79 ... NaN NaN NaN NaN
1  6523.95 6524.90 6525.00 6524.35 ... NaN NaN NaN NaN
2  6520.87 6520.00 6520.45 6520.46 ... NaN NaN NaN NaN
3  6516.34 6516.26 6516.21 6516.21 ... NaN NaN NaN NaN
4  6513.28 6514.00 6514.00 6514.00 ... NaN NaN NaN NaN
5  6511.98 6511.98 6511.99 6513.00 ... NaN NaN NaN NaN
6  6511.00 6511.00 6511.00 6511.00 ... NaN NaN NaN NaN
7  6511.70 6511.78 6511.99 6511.99 ... NaN NaN NaN NaN
8  6509.51 6510.00 6510.80 6510.80 ... NaN NaN NaN NaN
9  6511.36 6510.00 6510.00 6510.00 ... NaN NaN NaN NaN
10  6507.00 6507.00 6507.00 6507.00 ... NaN NaN NaN NaN
...  ...  ...  ...  ... ... ... ... ... ...
10386 6333.77 6331.31 6331.30 6333.19 ... NaN NaN NaN NaN
10387 6331.68 6331.30 6331.68  NaN ... NaN NaN NaN NaN
10388 6331.30 6331.30 6331.00 6331.00 ... NaN NaN NaN NaN
10389 6330.93 6330.92 6330.92 6330.93 ... NaN NaN NaN NaN
10390 6330.83 6330.83 6330.90 6330.80 ... NaN NaN NaN NaN
10391 6327.57 6326.00 6326.00 6325.74 ... NaN NaN NaN NaN
10392 6327.57 6329.70 6328.85 6328.85 ... NaN NaN NaN NaN
10393 6323.54 6323.15 6323.15 6322.77 ... NaN NaN NaN NaN
10394 6311.00 6310.83 6310.83 6310.50 ... NaN NaN NaN NaN
10395 6311.45 6311.32 6310.01 6310.01 ... NaN NaN NaN NaN
10396 6310.46 6310.46 6310.56 6311.61 ... NaN NaN NaN NaN
 
[10397 rows x 1147 columns]

可以看到行數是分組個數,一共1147列也是最多的那組數據長度。

之後我們通過調用fillna方法將缺失值進行填充,method=’ffill’是指以缺失值前一個數據為依據,axis = 1是以行為單位,limit是指最大填充長度。最終,把我們之前取得的timeseries添加到最後一列,就得到瞭需求的最終結果。

   0  1  2  ...  1145  1146  1148
0  6522.50 6522.66 6523.79 ...  6522.14 6522.14 25511135
1  6523.95 6524.90 6525.00 ...  6520.00 6520.00 25511136
2  6520.87 6520.00 6520.45 ...  6517.00 6517.00 25511137
3  6516.34 6516.26 6516.21 ...  6514.00 6514.00 25511138
4  6513.28 6514.00 6514.00 ...  6511.97 6511.97 25511139
5  6511.98 6511.98 6511.99 ...  6511.00 6511.00 25511140
6  6511.00 6511.00 6511.00 ...  6510.90 6510.90 25511141
7  6511.70 6511.78 6511.99 ...  6512.09 6512.09 25511142
8  6509.51 6510.00 6510.80 ...  6512.09 6512.09 25511143
9  6511.36 6510.00 6510.00 ...  6507.04 6507.04 25511144
10  6507.00 6507.00 6507.00 ...  6508.57 6508.57 25511145
11  6507.16 6507.74 6507.74 ...  6506.35 6506.35 25511146
...  ...  ...  ... ...   ...  ...  ...
10388 6331.30 6331.30 6331.00 ...  6331.00 6331.00 25521698
10389 6330.93 6330.92 6330.92 ...  6330.99 6330.99 25521699
10390 6330.83 6330.83 6330.90 ...  6327.58 6327.58 25521700
10391 6327.57 6326.00 6326.00 ...  6325.74 6325.74 25521701
10392 6327.57 6329.70 6328.85 ...  6325.00 6325.00 25521702
10393 6323.54 6323.15 6323.15 ...  6311.00 6311.00 25521703
10394 6311.00 6310.83 6310.83 ...  6315.00 6315.00 25521704
10395 6311.45 6311.32 6310.01 ...  6310.00 6310.00 25521705
10396 6310.46 6310.46 6310.56 ...  6314.04 6314.04 25521706
 
[10397 rows x 1148 columns]

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。

推薦閱讀: