如何在pandas数据框中拆分多行单元格的值?

时间:2017-05-02 06:06:32

标签: python pandas dataframe

我有一个以下数据框,它是使用代码获得的:

     df1=df.groupby('id')['x,y'].apply(lambda x: rdp(x.tolist(), 5.0)).reset_index()

参考here

获得的结果数据框:

      id          x,y
  0   1    [(0, 0), (1, 2)]
  1   2    [(1, 3), (1, 2)]
  2   3    [(2, 5), (4, 6)]  

是否有可能得到这样的东西:

         id      x,y
     0   1      (0, 0)
     1   1      (1, 2)
     2   2      (1, 3)
     3   2      (1, 2)
     4   3      (2, 5)
     5   3      (4, 6)

这里,作为前一个df的结果获得的坐标列表将根据各自的ID分成新行。

2 个答案:

答案 0 :(得分:5)

您可以将DataFrame构造函数与stack

一起使用
df2 = pd.DataFrame(df1['x,y'].values.tolist(), index=df1['id'])
        .stack()
        .reset_index(level=1, drop=True)
        .reset_index(name='x,y')
print (df2)

   id     x,y
0   1  (0, 0)
1   1  (1, 2)
2   2  (1, 3)
3   2  (1, 2)
4   3  (2, 5)
5   3  (4, 6)

numpy解决方案使用numpy.repeat lengths str.len之后numpy.ndarray.sum列的{{3}}列{@ 3}}列为{{3}}:

x,y

<强>计时

df2 = pd.DataFrame({'id': np.repeat(df1['id'].values, df1['x,y'].str.len()), 
                   'x,y': df1['x,y'].values.sum()})

print (df2)
   id     x,y
0   1  (0, 0)
0   1  (1, 2)
1   2  (1, 3)
1   2  (1, 2)
2   3  (2, 5)
2   3  (1, 9)
2   3  (4, 6)

答案 1 :(得分:2)

  • 计算新的'id'
    • 我们可以使用pandas str.len方法快速计算每个元素的子列表中的元素数量。这很方便,因为我们可以直接将此结果传递给repeat的{​​{1}}方法,该方法将从我们传递的长度中重复每个元素相应的数量。
  • 计算新的df1['id']
    • 通常,我喜欢使用'x,y'将所有子列表推送到一起。但是,在这种情况下,子列表是元组列表。 np.concatenate不会将这些视为对象列表。相反,我使用np.concatenate方法,它将在列表上使用基础sum方法,而这些方法将依次连接。

sum

如果我们坚持pandas,我们可以保持代码清洁
pandasrepeatstr.len

一起使用
sum

pd.DataFrame({ 'id': df1['id'].repeat(df1['x,y'].str.len()), 'x,y': df1['x,y'].sum() }) id x,y 0 1 (0, 0) 0 1 (1, 2) 1 2 (1, 3) 1 2 (1, 2) 2 3 (2, 5) 2 3 (4, 6)

我们可以通过使用底层的numpy数组和等效的numpy方法来加速这种方法
注意:这是等效的逻辑!

numpy

我们可以通过跳过pd.DataFrame({ 'id': df1['id'].values.repeat(df1['x,y'].str.len()), 'x,y': df1['x,y'].values.sum() }) 方法并使用列表理解来计算长度来加快速度。

str.len

时间测试

小数据

pd.DataFrame({
        'id': df1['id'].values.repeat([len(w) for w in df1['x,y'].values.tolist()]),
        'x,y': df1['x,y'].values.sum()
    })

更大的数据

%%timeit
pd.DataFrame({
        'id': df1['id'].values.repeat([len(w) for w in df1['x,y'].values.tolist()]),
        'x,y': df1['x,y'].values.sum()
    })
1000 loops, best of 3: 351 µs per loop

%%timeit
pd.DataFrame({
        'id': df1['id'].repeat(df1['x,y'].str.len()),
        'x,y': df1['x,y'].sum()
    })
1000 loops, best of 3: 590 µs per loop

%%timeit 
pd.DataFrame({'id': np.repeat(df1['id'].values, df1['x,y'].str.len()), 
                   'x,y': df1['x,y'].values.sum()})
​
1000 loops, best of 3: 498 µs per loop