通过列中的值扩展pandas数据框。

5
假设我有一个包含数据和数量列的数据框:
In:  df=pd.DataFrame({'first-name':['Jan','Leilani'],'Qty':[2,4]})

Out: Qty    first-name
     2      Jan
     4      Leilani

我想创建一个数据框,将每行的数据复制并标记到新的行中,次数等于每行的数量。以下是输出结果应该如何显示的示例:
Qty     first-name  position
2       Jan         1
2       Jan         2
4       Leilani     1
4       Leilani     2
4       Leilani     3
4       Leilani     4

我可以使用Python来完成这个任务,代码如下:
l=[]
x=0

for idx in df.index:
    x=0
    for _ in range(df.loc[idx]['Qty']):
        x+=1
        tempSrs=df.loc[idx]
        tempSrs['position']=x
        l.append(tempSrs)

outDf=pd.DataFrame(l)

这很慢。有没有一种方法可以使用pandas函数完成这个任务?实际上,这相当于“解除旋转”,在pandas中称为“melt”,但我无法弄清楚如何使用melt函数来完成此操作。

谢谢!


可能是使用单元格值将行相乘并附加到数据帧的重复问题。 - Zanshin
3个回答

7
使用 repeatcumcount
Newdf=df.reindex(df.index.repeat(df.Qty))
Newdf['position']=Newdf.groupby(level=0).cumcount()+1
Newdf
Out[931]: 
   Qty first-name position
0    2        jan        1
0    2        jan        2
1    4        jay        1
1    4        jay        2
1    4        jay        3
1    4        jay        4

2
精彩的答案 (-: - piRSquared
聪明。我不知道reindex和cumcount函数,谢谢你提供这个解决方案。 - Maile Cupo
@MaileCupo 没问题:-)愉快编程 - BENY
有点边缘情况,但很高兴有人问这个问题。非常有帮助。 - mmz

4

这个使用的概念与Wen几乎相同。

区别在于:

  1. loc替代reindex(同样的功能)
  2. assign替代=赋值(assign会产生一份副本)
  3. assign传递一个lambda函数来嵌入groupby逻辑

df.loc[df.index.repeat(df.Qty)].assign(
    position=lambda d: d.groupby('first-name').cumcount() + 1
)

   Qty first-name  position
0    2        jan         1
0    2        jan         2
1    4        jay         1
1    4        jay         2
1    4        jay         3
1    4        jay         4

使用np.arange创建数组

q = df.Qty.values
r = np.arange(q.sum()) - np.append(0, q[:-1]).cumsum().repeat(q) + 1
df.loc[df.index.repeat(q)].assign(position=r)

   Qty first-name  position
0    2        jan         1
0    2        jan         2
1    4        jay         1
1    4        jay         2
1    4        jay         3
1    4        jay         4

2

以下是使用 numpy.repeatitertools.chain 的直观方法。

对于较大的数据框,这种方法可能比 pandorable 方法更有效。

import pandas as pd
import numpy as np
from itertools import chain

df = pd.DataFrame({'first-name':['jan','jay'],'Qty':[2,4]})

lens = df['Qty'].values

res = pd.DataFrame({'Qty': np.repeat(df['Qty'], lens),
                    'first-name': np.repeat(df['first-name'], lens),
                    'Count': list(chain.from_iterable(range(1, i+1) for i in lens))})

print(res)

   Count  Qty first-name
0      1    2        jan
0      2    2        jan
1      1    4        jay
1      2    4        jay
1      3    4        jay
1      4    4        jay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接