【问题标题】:Convert column with list of tuples to many columns将具有元组列表的列转换为多列
【发布时间】:2018-12-04 10:36:19
【问题描述】:

我有一个数据框,其中一列包含不均匀的元组列表。元组的长度都相同,只有列表不均匀。我想在框架内熔化此列,以便将新列附加到现有列并复制行。像这样:

df
   name     id       list_of_tuples
0  john doe    abc-123  [('cat',100,'xyz-123'),('cat',96,'uvw-456')]
1  bob smith    def-456  [('dog',98,'rst-789'),('dog',97,'opq-123'),('dog',95,'lmn-123')]
2  bob parr    ghi-789  [('tree',100,'ijk-123')]

df_new
   name            id       val_1 val_2 val_3
0  john doe        abc-123  cat   100   xyz-123
1  john doe        abc-123  cat   96    uvw-456
2  bob smith       def-456  dog   98    rst-789
3  bob smith       def-456  dog   97    opq-123
4  violet parr     def-456  dog   95    lmn-123
5  violet parr     ghi-789  tree  100   ijk-123

对于我当前的方法,我正在创建一个新的数据框,我在其中使用来自 itertools 的链功能,但我想摆脱创建一个完整的其他数据框并将其合并回“id”列。

这是我当前的代码:

df_new = pd.DataFrame(list(chain.from_iterable(df.matches)),columns=['val_1','val_2','val_3']).reset_index(drop=True)
df_new['id'] = np.repeat(df.id.values, df['list_of_tuples'].str.len()) 

【问题讨论】:

    标签: python list pandas tuples


    【解决方案1】:

    取消你的列表然后我们做concat

    s=df.list_of_tuples
    pd.concat([pd.DataFrame({'id':df.id.repeat(s.str.len())}).reset_index(drop=True),pd.DataFrame(np.concatenate(s.values))],axis=1)
    Out[118]: 
            id     0    1        2
    0  abc-123   cat  100  xyz-123
    1  abc-123   cat   96  uvw-456
    2  def-456   dog   98  rst-789
    3  def-456   dog   97  opq-123
    4  def-456   dog   95  lmn-123
    5  ghi-789  tree  100  ijk-123
    

    【讨论】:

    • @guru 在这里再添加一列 pd.DataFrame({'id':df.id.repeat(s.str.len()),'name':df.name.repeat(s.str.len())}).reset_index(drop=True)
    【解决方案2】:

    在 0.25.3+ 中使用 pandas explode 更新

    dfi = df.explode('list_of_tuples')
    df1 = pd.DataFrame(dfi['list_of_tuples'].to_list(), 
                       index=[dfi['name'], dfi['id']])\
            .add_prefix('val_')
    df1.reset_index()
    

    输出:

            name       id val_0  val_1    val_2
    0   john doe  abc=123   cat    100  xyz-123
    1   john doe  abc=123   cat     96  uvw-456
    2  bob smith  def-456   dog     98  rst-789
    3  bob smith  def-456   dog     97  opq-123
    4  bob smith  def-456   dog     95  lmn-123
    5   bob parr  ghi-780  tree    100  ijk-123
    

    applypd.Series 一起使用:

    df.set_index('id').list_of_tuples  #Set id as index and select list_of_tuples column
      .apply(pd.Series)                #apply pd.series to separate elements of list 
      .stack()                         #stack the elements vertically
      .apply(pd.Series)                #apply pd.Series to separate elements of tuples
      .add_prefix('val_')              #add prefix of val_ to all columns
      .reset_index()                   #Reset index to move id back into frame as column
      .drop('level_1', axis=1)         #Drop not need level_1 column from stack
    

    输出:

            id val_0  val_1    val_2
    0  abc-123   cat    100  xyz-123
    1  abc-123   cat     96  uvw-456
    2  def-456   dog     98  rst-789
    3  def-456   dog     97  opq-123
    4  def-456   dog     95  lmn-123
    5  ghi-789  tree    100  ijk-123
    

    编辑处理将“名称”添加到数据框的问题编辑:

    df.set_index(['name','id']).list_of_tuples
      .apply(pd.Series)
      .stack()
      .apply(pd.Series)
      .add_prefix('val_')
      .reset_index(level=-1,drop=True)
      .reset_index()
    

    输出:

            name       id val_0  val_1    val_2
    0   John Doe  abc-123   cat    100  xyz-123
    1   John Doe  abc-123   cat     96  uvw-456
    2  Bob Smith  def-456   dog     98  rst-789
    3  Bob Smith  def-456   dog     97  opq-123
    4  Bob Smith  def-456   dog     95  lmn-123
    5   Bob Parr  ghi-789  tree    100  ijk-123
    

    【讨论】:

    • 感谢您的建议!但我会接受上面的评论,因为与 apply(pd.Series) 方法相比,它要快得多。
    • @guru 是的,是的。这是一种更快的方法。应用 pd.Series 很慢。温有完美的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    • 2016-09-28
    • 2018-12-19
    • 2012-11-02
    • 2015-02-13
    • 2011-07-27
    相关资源
    最近更新 更多