根据列表在熊猫数据框中复制行,并用列表条目填充新列

时间:2018-07-20 13:00:19

标签: python list pandas dataframe duplicates

我有一个关于在熊猫数据框中复制行的问题。我在列表中的“相关冲击”列中为每个观察分配了相关日期。观察值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可以做到吗?

2 个答案:

答案 0 :(得分:2)

从“相关冲击”列中,您可以使用applypd.Seriesstack为每个日期创建一行,例如:

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

我知道一个空缺,但是在您将joindfreset_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