[英]Unexpected number of bins in Pandas DataFrame resample
I need to reduce the length of a DataFrame to some externally defined integer (could be two rows, 10,000 rows, etc., but will always be a reduction in overall length), but I also want to keep the resulting DataFrame representative of the original . 原始 DataFrame(我們稱之為df
)有一個datetime
時間列( utc_time
)和一個數據值列( data_value
)。 日期時間始終是連續的、不重復的,盡管間隔不均勻(即,數據可能“丟失”)。 對於此示例中的 DataFrame,時間戳以十分鍾為間隔(當數據存在時)。
為了做到這一點,我立即想到了用以下邏輯重新采樣:找到第一個和最后一個時間戳之間的秒差,將其除以所需的最終長度,這就是重新采樣因子。 我在這里設置:
# Define the desired final length.
final_length = 2
# Define the first timestamp.
first_timestamp = df['utc_time'].min().timestamp()
# Define the last timestamp.
last_timestamp = df['utc_time'].max().timestamp()
# Define the difference in seconds between the first and last timestamps.
delta_t = last_timestamp - first_timestamp
# Define the resampling factor.
resampling_factor = np.ceil(delta_t / final_length)
# Set the index from the `utc_time` column so that we can resample nicely.
df.set_index('utc_time', drop=True, inplace=True)
# Do the resampling.
resamp = df.resample(f'{resampling_factor}S')
要查看resamp
,我只是循環並打印:
for i in resamp:
print(i)
這產生了(我進行了一些清理)以下內容:
utc_time data_value
2016-09-28 21:10:00 140.0
2016-09-28 21:20:00 250.0
2016-09-28 21:30:00 250.0
2016-09-28 21:40:00 240.0
2016-09-28 21:50:00 240.0
... ...
2018-08-06 13:00:00 240.0
2018-08-06 13:10:00 240.0
2018-08-06 13:20:00 240.0
2018-08-06 13:30:00 240.0
2018-08-06 13:40:00 230.0
[69889 rows x 1 columns])
utc_time data_value
2018-08-06 13:50:00 230.0
2018-08-06 14:00:00 230.0
2018-08-06 14:10:00 230.0
2018-08-06 14:20:00 230.0
2018-08-06 14:30:00 230.0
... ...
2020-06-14 02:50:00 280.0
2020-06-14 03:00:00 280.0
2020-06-14 03:10:00 280.0
2020-06-14 03:20:00 280.0
2020-06-14 03:30:00 280.0
[97571 rows x 1 columns])
utc_time data_value
2020-06-14 03:40:00 280.0
2020-06-14 03:50:00 280.0
2020-06-14 04:00:00 280.0
2020-06-14 04:10:00 280.0
2020-06-14 04:20:00 280.0
... ...
2020-06-15 00:10:00 280.0
2020-06-15 00:20:00 270.0
2020-06-15 00:30:00 270.0
2020-06-15 00:40:00 270.0
2020-06-15 00:50:00 280.0
[128 rows x 1 columns])
可以看到,這產生了三個垃圾箱,而不是我預期的兩個垃圾箱。
我可以做一些不同的事情,比如改變我選擇重采樣因子的方式(例如,找到時間戳之間的平均時間,並將其乘以(DataFrame / final_length
的長度)應該會產生一個更保守的重采樣因子),但這會我的想法,成為潛在問題的面具。 主要是,我很想了解為什么會發生這種情況。 這導致...
有誰知道為什么會發生這種情況,以及我可能會采取哪些步驟來確保我們獲得所需數量的垃圾箱? 我想知道這是否是一個抵消問題 - 也就是說,盡管我們將第一個 bin 中的第一個時間戳視為 DataFrame 的第一個時間戳,但也許 pandas 實際上是在那之前開始 bin 的?
對於任何想在家一起玩的人,測試 DataFrame 可以在這里找到a.csv。 以 DataFrame 的形式獲取它:
df = pd.read_csv('test.csv', parse_dates=[0])
問題 1 和修復:您形成垃圾箱的方式會產生一個額外的垃圾箱,因為使用df.resample()
創建的垃圾箱將僅在一端(左側或右側)關閉。 使用“1.”中列出的選項之一修復此問題。
問題 2 和修復:第一個 bin 左邊緣位於當天開始時('2016-09-28 00:00:00')(參見“2.”)。 您可以使用kind='period'
作為resample()
的參數來修復它。 (見“3”)
輸入數據是從2016-09-28 21:10:00
到2020-06-15 00:50:00
,使用你擁有的resampling_factor
,我們得到:
In [63]: df.index.min()
Out[63]: Timestamp('2016-09-28 21:10:00')
In [64]: df.index.min() + pd.Timedelta(f'{resampling_factor}S')
Out[64]: Timestamp('2018-08-07 11:00:00')
In [65]: _ + pd.Timedelta(f'{resampling_factor}S')
Out[65]: Timestamp('2020-06-15 00:50:00')
要使用這些時間戳將數據分成兩部分,我們需要將 bin
['2016-09-28 21:10:00', '2018-08-07 11:00:00')
['2018-08-07 11:00:00', '2020-06-15 00:50:00']
( [
表示封閉端, (
表示開放端)
closed='left'|'right'
,)。 使用closed='left'
你會有
['2016-09-28 21:10:00', '2018-08-07 11:00:00')
['2018-08-07 11:00:00', '2020-06-15 00:50:00')
['2020-06-15 00:50:00', '2022-04-23 14:40:00')
(這里只有一個條目) 可能的修復:
last_timestamp = (df['utc_time'].max() +
pd.Timedelta('10 minutes')).timestamp()
resampling_factor
比你第一次計算的大一點。df.resample
中的前兩個數據幀,而忽略只有一個或幾個條目的第三個數據幀選擇在您的應用程序中最有意義的選項。
df.resample
文檔中,我們知道返回的標簽是左 bin 邊緣
In [67]: resamp = df.resample(f'{resampling_factor}S')
In [68]: itr = iter(resamp)
In [69]: next(itr)
Out[69]:
(Timestamp('2016-09-28 00:00:00', freq='58542600S'),
data_value
utc_time
2016-09-28 21:10:00 140.0
... ...
2018-08-06 13:40:00 230.0
[69889 rows x 1 columns])
In [70]: next(itr)
Out[70]:
(Timestamp('2018-08-06 13:50:00', freq='58542600S'),
data_value
utc_time
2018-08-06 13:50:00 230.0
... ...
2020-06-14 03:30:00 280.0
[97571 rows x 1 columns])
In [71]: next(itr)
Out[71]:
(Timestamp('2020-06-14 03:40:00', freq='58542600S'),
data_value
utc_time
2020-06-14 03:40:00 280.0
... ...
2020-06-15 00:50:00 280.0
[128 rows x 1 columns])
['2016-09-28 00:00:00', '2018-08-06 13:50:00')
['2018-08-06 13:50:00', '2020-06-14 03:40:00')
['2020-06-14 03:40:00', '2022-04-22 17:30:00')
(通過將resampling_factor
添加到 bin 的開頭來計算端點。)df['utc_time'].min
( 2016-09-28 21:10:00
) 開始的,而是從那天開始的時候開始的(正如你猜到的) kind
參數可以是'timestamp'
或'period'
。 如果將其更改為'period'
,您將擁有以下垃圾箱(使用closed='left'
):
['2016-09-28 21:10:00', '2018-08-07 11:00:00')
<-- 固定['2018-08-07 11:00:00', '2020-06-15 00:50:00')
['2020-06-15 00:50:00', '2022-04-23 14:40:00')
(使用“1.”中給出的選項刪除)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.