我有一个关于在熊猫数据框中复制行的问题。我在列表中的“相关冲击”列中为每个观察分配了相关日期。观察值22的列表为空,23为一个日期的列表,24为两个日期的列表,25为三个日期的列表(如“ listlength”列所示)。
我的目标是扩展数据框架,使具有空列表的观察结果保留在数据集中仅一行,而具有x个观察结果的行则重复x次-因此,第22和23行应保留在数据框中一次(22尽管有一个空列表,而第23行是因为它有一个相关的日期),但第24行应重复一次,因此在数据框中是两次,而观察值25应该重复两次,因此在数据框中是三次。这样,每一行在数据帧中应具有相关冲击的次数(以列表长度衡量)。除了列表长度为0的列表,它们仍应保留在数据框中。
此外,我想创建一个新列“相关冲击”,该列由每个相关冲击分别填充一次。
这是当前数据框:
quarter year pddate relevant shocks listlength
22 1 2012 2012-02-15 [] 0.0
23 4 2011 2011-11-15 [2011-08-18 00:00:00] 1.0
24 3 2011 2011-08-15 [2011-08-18 00:00:00, 2011-09-22 00:00:00] 2.0
25 2 2011 2011-05-13 [2011-08-04 00:00:00, 2011-08-08 00:00:00, 2011-08-10 00:00:00 3.0
新数据框应具有7行,如下所示:
quarter year pddate relevant shocks listlength relevant shock
22 1 2012 2012-02-15 [] 0.0
23 4 2011 2011-11-15 [2011-08-18 00:00:00] 1.0 2011-08-18 00:00:00
24 3 2011 2011-08-15 [2011-08-18 00:00:00, 2011-09-22 00:00:00] 2.0 2011-08-18 00:00:00
25 3 2011 2011-08-15 [2011-08-18 00:00:00, 2011-09-22 00:00:00] 2.0 2011-09-22 00:00:00
26 2 2011 2011-05-13 [2011-08-04 00:00:00, 2011-08-08 00:00:00, 2011-08-10 00:00:00 3.0 2011-08-04 00:00:00
27 2 2011 2011-05-13 [2011-08-04 00:00:00, 2011-08-08 00:00:00, 2011-08-10 00:00:00 3.0 2011-08-08 00:00:00
28 2 2011 2011-05-13 [2011-08-04 00:00:00, 2011-08-08 00:00:00, 2011-08-10 00:00:00 3.0 2011-08-10 00:00:00
因此,基本思路是添加新列“相关冲击”,遍历每一行,如果“相关冲击”中有一个空白列表,则保持不变;如果“相关冲击”中有一个日期,则保持不变。相关冲击”,但用该列表项填充新列“相关冲击”,如果在“相关冲击”中有两个列表项,则将其复制,然后在每行中用两个列表项之一填充“相关冲击”列,依次类推。
Python可以做到吗?
答案 0 :(得分:2)
从“相关冲击”列中,您可以使用apply
,pd.Series
和stack
为每个日期创建一行,例如:
df['relevant shocks'].apply(pd.Series).stack()
Out[448]:
23 0 2011-08-18 00:00:00
24 0 2011-08-18 00:00:00
1 2011-09-22 00:00:00
25 0 2011-08-04 00:00:00
1 2011-08-08 00:00:00
2 2011-08-10 00:00:00
dtype: object
我知道一个空缺,但是在您将join
,df
和reset_index
多余的列fillna
存入您的drop
之后。像这样的df
:
df = pd.DataFrame({'quarter':[1,2,3,4],
'relevant shocks':[[],['2011-08-18 00:00:00'],
['2011-08-18 00:00:00', '2011-09-22 00:00:00'],
['2011-08-04 00:00:00', '2011-08-08 00:00:00', '2011-08-10 00:00:00']]},
index=[22,23,24,25])
然后您这样做:
df = (df.join(df['relevant shocks'].apply(pd.Series).stack()
.reset_index(1,name='relevant shock'))
.fillna('').drop('level_1',1))
您会得到:
quarter relevant shocks \
22 1 []
23 2 [2011-08-18 00:00:00]
24 3 [2011-08-18 00:00:00, 2011-09-22 00:00:00]
24 3 [2011-08-18 00:00:00, 2011-09-22 00:00:00]
25 4 [2011-08-04 00:00:00, 2011-08-08 00:00:00, 201...
25 4 [2011-08-04 00:00:00, 2011-08-08 00:00:00, 201...
25 4 [2011-08-04 00:00:00, 2011-08-08 00:00:00, 201...
relevant shock
22
23 2011-08-18 00:00:00
24 2011-08-18 00:00:00
24 2011-09-22 00:00:00
25 2011-08-04 00:00:00
25 2011-08-08 00:00:00
25 2011-08-10 00:00:00
编辑:对于实际数据,空列表似乎发生了错误,因此要解决它,最后reset_index
进行解决:
df = (df.join(df.loc[df['relevant shocks'].str.len() > 0, 'relevant shocks']
.apply(pd.Series).stack().reset_index(1,name='relevant shock'))
.fillna('').drop('level_1',1).reset_index(drop=True))
答案 1 :(得分:0)
现在可以使用pandas.DataFrame.explode