根据列值在pandas DataFrame中重复行

36
我有以下的数据框:
code . role    . persons
123 .  Janitor . 3
123 .  Analyst . 2
321 .  Vallet  . 2
321 .  Auditor . 5

第一行的意思是我有3个担任清洁工角色的人。 我的问题是我需要每个人都有一行。我的数据框应该是这样的:
df:

code . role    . persons
123 .  Janitor . 3
123 .  Janitor . 3
123 .  Janitor . 3
123 .  Analyst . 2
123 .  Analyst . 2
321 .  Vallet  . 2
321 .  Vallet  . 2
321 .  Auditor . 5
321 .  Auditor . 5
321 .  Auditor . 5
321 .  Auditor . 5
321 .  Auditor . 5

如何使用pandas来实现这个功能呢?

可能重复:根据不同列中的值复制行 - Sam Firke
4个回答

64

reindexrepeat的作用

df.reindex(df.index.repeat(df.persons))
Out[951]: 
   code  .     role ..1  persons
0   123  .  Janitor   .        3
0   123  .  Janitor   .        3
0   123  .  Janitor   .        3
1   123  .  Analyst   .        2
1   123  .  Analyst   .        2
2   321  .   Vallet   .        2
2   321  .   Vallet   .        2
3   321  .  Auditor   .        5
3   321  .  Auditor   .        5
3   321  .  Auditor   .        5
3   321  .  Auditor   .        5
3   321  .  Auditor   .        5

提示:你可以添加.reset_index(drop=True)来获取新的索引


太棒了,我知道有一个好的解决方案是使用repeat,但这个方法非常完美。 - cs95
3
好的,这很不错。也许最后再加一个 reset_index() 函数呢? - Anton vBR
1
@Wen 我喜欢学习新东西!你会相信,我以前不知道可以在重新索引中重复使用索引值。我一直使用重新索引来洗牌或添加索引,但从未像你这样复制过。太棒了。干得好。+1 - Scott Boston
@ScottBoston 谢谢你,伙计 :-) SO 是一个很好的地方,让我们相互学习(我很久以前从 coldspeed 那里学到了这一点 :-) ) - BENY

17

Wen的解决方案非常好,易于理解,但是如果有重复的行,它将抛出ValueError: cannot reindex from a duplicate axis异常。

以下是一种替代方案,通过在df.values上调用repeat来避免这种情况。

df

   code     role  persons
0   123  Janitor        3
1   123  Analyst        2
2   321   Vallet        2
3   321  Auditor        5


pd.DataFrame(df.values.repeat(df.persons, axis=0), columns=df.columns)

   code     role persons
0   123  Janitor       3
1   123  Janitor       3
2   123  Janitor       3
3   123  Analyst       2
4   123  Analyst       2
5   321   Vallet       2
6   321   Vallet       2
7   321  Auditor       5
8   321  Auditor       5
9   321  Auditor       5
10  321  Auditor       5
11  321  Auditor       5

就性能而言,是使用.reindex()更好还是.values.repeat()更好? - lmiguelvargasf
1
@lmiguelvargasf 这个解决方案更快。但是温的解决方案需要更少的字符,并且我足够友好,在他的答案下留了一个好评,这激发了所有额外的赞成票。 - cs95
1
我看到你的解决方案唯一的问题是,数据框中每一列的 dtypes 都被更改为 object - lmiguelvargasf
1
这个方法适用于有重复行的情况,而不同于BENY的解决方案,后者会抛出一个 ValueError (ValueError: cannot reindex from a duplicate axis) 异常。 - There

4

声望不够,无法发表评论,但可以借鉴 @cs95 回答和 @lmiguelvargasf 的评论,并使用以下方法保留 dtypes:

pd.DataFrame(
    df.values.repeat(df.persons, axis=0),
    columns=df.columns,
).astype(df.dtypes)

2

你可以使用 Series 方法 repeat

df = pd.DataFrame({'col1': [2, 3],
                   'col2': ['a', 'b'],
                   'col3': [20, 30]})

df.apply(lambda x: x.repeat(df['col1']))
# df.apply(pd.Series.repeat, repeats=df['col1'])

或者使用numpy函数repeat

df.apply(np.repeat, repeats=df['col1'])

输出:

   col1 col2  col3
0     2    a    20
0     2    a    20
1     3    b    30
1     3    b    30
1     3    b    30

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