将 pandas df 与 "list column" 中的数据转换为长格式的时间序列。使用三列:[数据列表] + [时间戳] + [持续时间]
Convert pandas df with data in a "list column" into a time series in long format. Use three columns: [list of data] + [timestamp] + [duration]
目的是将一个以列表列作为数据列的数据帧(因此每行只有一个时间戳和持续时间)转换为长格式的时间序列,每个项目都有一个 datetimeindex
.
在结果中,不再有数据的每行 sequence/list,而是只有一个 value
列。
df_test = pd.DataFrame({'timestamp': [1462352000000000000, 1462352100000000000, 1462352200000000000, 1462352300000000000],
'list': [[1,2,1,9], [2,2,3,0], [1,3,3,0], [1,1,3,9]],
'duration_sec': [3.0, 3.0, 3.0, 3.0]})
tdi = pd.DatetimeIndex(df_test.timestamp)
df_test.set_index(tdi, inplace=True)
df_test.drop(columns='timestamp', inplace=True)
df_test.index.name = 'datetimeindex'
输出:
list duration_sec
datetimeindex
2016-05-04 08:53:20 [1, 2, 1, 9] 3.0
2016-05-04 08:55:00 [2, 2, 3, 0] 3.0
2016-05-04 08:56:40 [1, 3, 3, 0] 3.0
2016-05-04 08:58:20 [1, 1, 3, 9] 3.0
目标是:
value
datetimeindex
2016-05-04 08:53:20 1
2016-05-04 08:53:21 2
2016-05-04 08:53:22 1
2016-05-04 08:53:23 9
2016-05-04 08:55:00 2
2016-05-04 08:55:01 2
2016-05-04 08:55:02 3
2016-05-04 08:55:03 0
2016-05-04 08:56:40 1
2016-05-04 08:56:41 3
2016-05-04 08:56:42 3
2016-05-04 08:56:43 0
2016-05-04 08:58:20 1
2016-05-04 08:58:21 1
2016-05-04 08:58:22 3
2016-05-04 08:58:23 9
请注意,这意味着不仅仅是每个项目需要 1 秒;这只是为了简化示例。相反,它是一个序列中的大约 4 个项目,具有给定的持续时间,例如 3.0 秒(也可能因行而异),并且每个序列的第一个项目始终从“时间 0”开始,这意味着每个项目的秒数应该计算为
[3.0 sec / (4-1) items] = 1 sec.
上下文:
该示例显示转换为 Datetimeindex
,因为这使其适合 seasonal_decompose()
,请参见 this 第一个搜索命中。
在那里,生成的 df 如下所示:
df_test2 = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
输出:
value
date
1991-07-01 3.526591
1991-08-01 3.180891
1991-09-01 3.252221
1991-10-01 3.611003
1991-11-01 3.565869
...
2008-02-01 21.654285
2008-03-01 18.264945
2008-04-01 23.107677
2008-05-01 22.912510
2008-06-01 19.431740
[204 rows x 1 columns]
然后很容易通过 additive
分解模型应用 seasonal_decompose()
:
result_add = seasonal_decompose(df_test2['value'], model='additive', extrapolate_trend='freq')
# Plot
plt.rcParams.update({'figure.figsize': (5,5)})
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()
现在上面的 df_test
也需要同样的东西。
使用DataFrame.explode
first and then add counter by GroupBy.cumcount
and to_timedelta
到df.index
:
df_test = df_test.explode('nestedList')
df_test.index += pd.to_timedelta(df_test.groupby(level=0).cumcount(), unit='s')
print (df_test)
nestedList duration_sec
2016-05-04 08:53:20 1 3.0
2016-05-04 08:53:21 2 3.0
2016-05-04 08:53:22 1 3.0
2016-05-04 08:53:23 9 3.0
2016-05-04 08:55:00 2 3.0
2016-05-04 08:55:01 2 3.0
2016-05-04 08:55:02 3 3.0
2016-05-04 08:55:03 0 3.0
2016-05-04 08:56:40 1 3.0
2016-05-04 08:56:41 3 3.0
2016-05-04 08:56:42 3 3.0
2016-05-04 08:56:43 0 3.0
2016-05-04 08:58:20 1 3.0
2016-05-04 08:58:21 1 3.0
2016-05-04 08:58:22 3 3.0
2016-05-04 08:58:23 9 3.0
编辑:
df_test = df_test.explode('nestedList')
sizes = df_test.groupby(level=0)['nestedList'].transform('size').sub(1)
duration = df_test['duration_sec'].div(sizes)
df_test.index += pd.to_timedelta(df_test.groupby(level=0).cumcount() * duration, unit='s')
提问者编辑 2:
有了生成的 df,decompose() 的这种简单应用现在成为可能,这是最终目标:
result_add = seasonal_decompose(x=df_test['nestedList'], model='additive', extrapolate_trend='freq', period=int(len(df_test)/2))
plt.rcParams.update({'figure.figsize': (5,5)})
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()
目的是将一个以列表列作为数据列的数据帧(因此每行只有一个时间戳和持续时间)转换为长格式的时间序列,每个项目都有一个 datetimeindex
.
在结果中,不再有数据的每行 sequence/list,而是只有一个 value
列。
df_test = pd.DataFrame({'timestamp': [1462352000000000000, 1462352100000000000, 1462352200000000000, 1462352300000000000],
'list': [[1,2,1,9], [2,2,3,0], [1,3,3,0], [1,1,3,9]],
'duration_sec': [3.0, 3.0, 3.0, 3.0]})
tdi = pd.DatetimeIndex(df_test.timestamp)
df_test.set_index(tdi, inplace=True)
df_test.drop(columns='timestamp', inplace=True)
df_test.index.name = 'datetimeindex'
输出:
list duration_sec
datetimeindex
2016-05-04 08:53:20 [1, 2, 1, 9] 3.0
2016-05-04 08:55:00 [2, 2, 3, 0] 3.0
2016-05-04 08:56:40 [1, 3, 3, 0] 3.0
2016-05-04 08:58:20 [1, 1, 3, 9] 3.0
目标是:
value
datetimeindex
2016-05-04 08:53:20 1
2016-05-04 08:53:21 2
2016-05-04 08:53:22 1
2016-05-04 08:53:23 9
2016-05-04 08:55:00 2
2016-05-04 08:55:01 2
2016-05-04 08:55:02 3
2016-05-04 08:55:03 0
2016-05-04 08:56:40 1
2016-05-04 08:56:41 3
2016-05-04 08:56:42 3
2016-05-04 08:56:43 0
2016-05-04 08:58:20 1
2016-05-04 08:58:21 1
2016-05-04 08:58:22 3
2016-05-04 08:58:23 9
请注意,这意味着不仅仅是每个项目需要 1 秒;这只是为了简化示例。相反,它是一个序列中的大约 4 个项目,具有给定的持续时间,例如 3.0 秒(也可能因行而异),并且每个序列的第一个项目始终从“时间 0”开始,这意味着每个项目的秒数应该计算为
[3.0 sec / (4-1) items] = 1 sec.
上下文:
该示例显示转换为 Datetimeindex
,因为这使其适合 seasonal_decompose()
,请参见 this 第一个搜索命中。
在那里,生成的 df 如下所示:
df_test2 = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
输出:
value
date
1991-07-01 3.526591
1991-08-01 3.180891
1991-09-01 3.252221
1991-10-01 3.611003
1991-11-01 3.565869
...
2008-02-01 21.654285
2008-03-01 18.264945
2008-04-01 23.107677
2008-05-01 22.912510
2008-06-01 19.431740
[204 rows x 1 columns]
然后很容易通过 additive
分解模型应用 seasonal_decompose()
:
result_add = seasonal_decompose(df_test2['value'], model='additive', extrapolate_trend='freq')
# Plot
plt.rcParams.update({'figure.figsize': (5,5)})
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()
现在上面的 df_test
也需要同样的东西。
使用DataFrame.explode
first and then add counter by GroupBy.cumcount
and to_timedelta
到df.index
:
df_test = df_test.explode('nestedList')
df_test.index += pd.to_timedelta(df_test.groupby(level=0).cumcount(), unit='s')
print (df_test)
nestedList duration_sec
2016-05-04 08:53:20 1 3.0
2016-05-04 08:53:21 2 3.0
2016-05-04 08:53:22 1 3.0
2016-05-04 08:53:23 9 3.0
2016-05-04 08:55:00 2 3.0
2016-05-04 08:55:01 2 3.0
2016-05-04 08:55:02 3 3.0
2016-05-04 08:55:03 0 3.0
2016-05-04 08:56:40 1 3.0
2016-05-04 08:56:41 3 3.0
2016-05-04 08:56:42 3 3.0
2016-05-04 08:56:43 0 3.0
2016-05-04 08:58:20 1 3.0
2016-05-04 08:58:21 1 3.0
2016-05-04 08:58:22 3 3.0
2016-05-04 08:58:23 9 3.0
编辑:
df_test = df_test.explode('nestedList')
sizes = df_test.groupby(level=0)['nestedList'].transform('size').sub(1)
duration = df_test['duration_sec'].div(sizes)
df_test.index += pd.to_timedelta(df_test.groupby(level=0).cumcount() * duration, unit='s')
提问者编辑 2:
有了生成的 df,decompose() 的这种简单应用现在成为可能,这是最终目标:
result_add = seasonal_decompose(x=df_test['nestedList'], model='additive', extrapolate_trend='freq', period=int(len(df_test)/2))
plt.rcParams.update({'figure.figsize': (5,5)})
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()