Pandas 创建时间序列并将其提取到新数据帧
Posted
技术标签:
【中文标题】Pandas 创建时间序列并将其提取到新数据帧【英文标题】:Pandas create and extract Time Series to new dataframe 【发布时间】:2019-04-08 04:24:32 【问题描述】:有以下简化的数据框:
Date Name Score V H M
2018-01-01 A 5 V1 H4 M6
2018-01-01 B 3 V5 H2 M1
2018-01-01 C 4 V7 H6 M6
2018-01-01 A 4 V11 H9 M3
2018-01-01 C 2 V4 H2 M18
2018-01-02 A 4 V9 H1 M9
2018-01-02 B 1 V15 H4 M10
2018-01-02 A 3 V10 H10 M14
2018-01-03 C 5 V5 H21 M34
2018-01-04 A 3 V8 H9 M6
2018-01-04 A 4 V4 H15 M9
2018-01-04 C 2 V2 H4 M14
2018-01-04 B 5 V1 H1 M2
将上述数据框视为原始集,我进一步按日期对其进行了索引,并按月重新采样。我最终想做的是为列(名称、V、H、M)中与分数相关的唯一值创建单独的时间序列(通过分组完成)。虽然我已经进行了下采样,但我预计这些列的分组唯一值的时间序列大小不规则,并计划进行插值来处理。
目标是创建多个时间序列并将其提取到一个新的数据帧中,并探索它们的相关图。例如,我将有 V1、V2、...、Vn、H1、H2、...、Hn、M1、M2、...、Mn 等的单独时间序列。
我不确定这是否应该全部捕获在一个新数据帧或基于分组的多个数据帧中。以下是时间序列输出的示例:
Date Score
V1 2018-01-01 4.5
2018-02-01 4.1
2018-03-01 4.3
2018-04-01 4.2
2018-05-01 4.4
Date Score
V2 2018-01-01 4.5
2018-02-01 4.1
2018-03-01 4.3
2018-04-01 4.2
2018-05-01 4.4
Date Score
V3 2018-01-01 4.5
2018-02-01 4.1
2018-03-01 4.3
2018-04-01 4.2
2018-05-01 4.4
我需要帮助来实施有效的方法来执行此操作并了解我是否走在正确的轨道上。上面的数据框是更大数据集的简化版本。
感谢任何帮助和指导。
【问题讨论】:
预期输出是什么? 嗨,编辑了帖子以阐明预期的输出。我希望将时间序列从原始数据提取到一个新的数据帧(或者可能是基于从列中提取的分组的多个数据帧)。为混乱道歉。 所以代码应该从每日变为每月?以及如何处理在同一时间段内对于同一个键有多个值的情况?你平均吗? 没错。从某种意义上说,这不是定期的每日,有些日子可能会在这里或那里丢失,而在某些日子里,任何列中的任何唯一值实际上可能有多个分数。因此,我通过每月重新采样并采用我能够容纳重复项的平均值来处理这个问题。 【参考方案1】:我用 pandas melt
试过这个。我试图使用双 melt
,但 this SO post 解释说不能这样做,所以我不得不(1)melt
(堆栈)在除Score
列之外的列上给出df_modmelt
,然后(b ) 附加一个新列,它只是 Score
列 based on this idea 的重复版本 - 本质上,同一列已重复(垂直连接)n
次:我使用 (len(df_modmelt)/len(df))
完成此操作。这是有道理的,因为在熔化后,我没有更改行顺序,因此熔化数据帧df_modmelt
中的每个块与原始数据的顺序相同,并且附加Scores
列保留了Scores
列之间的关联和其他人。然后只需使用Grouper
with key='Date'
and freq='M'
。
这是示例代码(我在您的示例数据中附加了 3 行以获取第 2 个月的一些值)
df['Date'] = pd.to_datetime(df['Date'])
Date Name Score V H M
0 2018-01-01 A 5 V1 H4 M6
1 2018-01-01 B 3 V5 H2 M1
2 2018-01-01 C 4 V7 H6 M6
3 2018-01-01 A 4 V11 H9 M3
4 2018-01-01 C 2 V4 H2 M18
5 2018-01-02 A 4 V9 H1 M9
6 2018-01-02 B 1 V15 H4 M10
7 2018-01-02 A 3 V10 H10 M14
8 2018-01-03 C 5 V5 H21 M34
9 2018-01-04 A 3 V8 H9 M6
10 2018-01-04 A 4 V4 H15 M9
11 2018-01-04 C 2 V2 H4 M14
12 2018-01-04 B 5 V1 H1 M2
13 2018-02-01 A 4 V5 H11 M9
14 2018-02-01 C 2 V7 H5 M14
15 2018-02-02 B 5 V1 H7 M2
代码
cols = ['V','H','M','Name']
df_modmelt = (df[['Date']+cols]
.melt(id_vars=['Date'],
var_name='column',
value_name='value'))
df_modmelt['Score'] = (pd.concat([df['Score']]*(len(df_modmelt)/len(df)))
.reset_index(drop=True))
df_final = (df_modmelt
.groupby(['column','value', pd.Grouper(key='Date', freq='M')])['Score']
.mean()
.reset_index(drop=False))
df_final['Date'] = df_final['Date'].dt.floor('d') - pd.offsets.MonthBegin(1)
print(df_final)
这是输出
column value Date Score
0 H H1 2018-01-01 4.500000
1 H H10 2018-01-01 3.000000
2 H H11 2018-02-01 4.000000
3 H H15 2018-01-01 4.000000
4 H H2 2018-01-01 2.500000
5 H H21 2018-01-01 5.000000
6 H H4 2018-01-01 2.666667
7 H H5 2018-02-01 2.000000
8 H H6 2018-01-01 4.000000
9 H H7 2018-02-01 5.000000
10 H H9 2018-01-01 3.500000
11 M M1 2018-01-01 3.000000
12 M M10 2018-01-01 1.000000
13 M M14 2018-01-01 2.500000
14 M M14 2018-02-01 2.000000
15 M M18 2018-01-01 2.000000
16 M M2 2018-01-01 5.000000
17 M M2 2018-02-01 5.000000
18 M M3 2018-01-01 4.000000
19 M M34 2018-01-01 5.000000
20 M M6 2018-01-01 4.000000
21 M M9 2018-01-01 4.000000
22 M M9 2018-02-01 4.000000
23 Name A 2018-01-01 3.833333
24 Name A 2018-02-01 4.000000
25 Name B 2018-01-01 3.000000
26 Name B 2018-02-01 5.000000
27 Name C 2018-01-01 3.250000
28 Name C 2018-02-01 2.000000
29 V V1 2018-01-01 5.000000
30 V V1 2018-02-01 5.000000
31 V V10 2018-01-01 3.000000
32 V V11 2018-01-01 4.000000
33 V V15 2018-01-01 1.000000
34 V V2 2018-01-01 2.000000
35 V V4 2018-01-01 3.000000
36 V V5 2018-01-01 4.000000
37 V V5 2018-02-01 4.000000
38 V V7 2018-01-01 4.000000
39 V V7 2018-02-01 2.000000
40 V V8 2018-01-01 3.000000
41 V V9 2018-01-01 4.000000
编辑
最后一行 pd.offsets.MonthBegin(1)
只是返回该月的第一个日期。
编辑 2
根据请求获取有关unique values in the value
column 与df_final
之间相关性的更多信息 - 请参阅有用链接here:
for c in ['Name','H']:
df_pivot = (df_final[df_final.value.isin(df[c].unique().tolist())]
.pivot_table(index='Date', columns='value', values='Score'))
Name
列的输出
print(df_pivot)
value A B C
Date
2018-01-01 3.833333 3.0 3.25
2018-02-01 4.000000 5.0 2.00
print(df_pivot.corr())
value A B C
value
A 1.0 1.0 -1.0
B 1.0 1.0 -1.0
C -1.0 -1.0 1.0
H
列的输出
print(df_pivot)
value H1 H10 H11 H15 H2 H21 H4 H5 H6 H7 H9
Date
2018-01-01 4.5 3.0 NaN 4.0 2.5 5.0 2.666667 NaN 4.0 NaN 3.5
2018-02-01 NaN NaN 4.0 NaN NaN NaN NaN 2.0 NaN 5.0 NaN
print(df_pivot.corr())
value H1 H10 H11 H15 H2 H21 H4 H5 H6 H7 H9
value
H1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
H10 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
H11 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
H15 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
H2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
H21 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
H4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
H5 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
H6 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
H7 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
H9 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
【讨论】:
非常感谢您的评论,这是一个非常有趣的输出。因此,如果我想按唯一列值(例如 groupby H1、H2、H3 等)进行分组,我会使用 df.get_group(unique_value) 之类的东西吗?我怎样才能以迭代的方式做到这一点?我的目标是将这些时间序列输入相关图(每个名称、V、H 和 M 1 个图) 我已经发布了一种使用 pandaspivot_table
为列 H
和 Name
执行此操作的方法。在示例数据中,将有NaN
s 缺少数据。据推测,在您的真实数据中,NaN
s 较少。仅供参考:可能最好在新问题中要求修改......它使 OP 保持清洁和结构化。
再次感谢您 - 非常感谢您提供的方法和资源链接。超级翔实。我会仔细阅读它们,如果我有任何需要修改的问题,我一定会提出一个新问题。感谢您的时间。【参考方案2】:
您可以使用concat
将列名称、V、H、M 移到彼此下方。之后,您可以使用tile
填写分数。最后,您可以将resample
、mean
和interpolate
应用于以下组:
import numpy as np
df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)
df2 = pd.concat([df.Name, df.V, df.H, df.M]).to_frame(name='Name')
df2['Score'] = np.tile(df['Score'].values,4)
df2.groupby('Name').apply(lambda x: x.resample('M').mean().interpolate())
【讨论】:
非常感谢您采用这种方法。 np.tile() 在 concat() 之后非常方便。有没有办法可以根据它们的分组来解析时间序列?例如,我可以使用列 Name、V、H、M 中的唯一分组迭代地填充新数据框吗? 我不明白你的问题。也许你可以用一些预期的输出来编辑你的问题以进行澄清。以上是关于Pandas 创建时间序列并将其提取到新数据帧的主要内容,如果未能解决你的问题,请参考以下文章