【问题标题】:Replicating rows in a pandas data frame by a column value [duplicate]通过列值复制熊猫数据框中的行
【发布时间】:2020-07-07 00:34:49
【问题描述】:

我想复制 Pandas 数据框中的行。每行应重复 n 次,其中 n 是每行的一个字段。

import pandas as pd

what_i_have = pd.DataFrame(data={
  'id': ['A', 'B', 'C'],
  'n' : [  1,   2,   3],
  'v' : [ 10,  13,   8]
})

what_i_want = pd.DataFrame(data={
  'id': ['A', 'B', 'B', 'C', 'C', 'C'],
  'v' : [ 10,  13,  13,   8,   8,   8]
})

这可能吗?

【问题讨论】:

  • 有什么理由这样做吗?我认为最好避免数据重复。
  • 这是一个中间步骤——我根据概率分布生成“v”列,然后我将通过从另一个数据集中随机选择行来添加另一列。
  • 我仍然没有看到不直接这样做的理由。但我需要更多关于你实际想要达到的目标的信息。
  • 不确定这里的“直接做”是什么意思?不过,接受的答案正是我想要的。
  • 在将因子转换为虚拟变量之前,我正在使用这个中间步骤。

标签: python pandas


【解决方案1】:

您可以使用Index.repeat根据列获取重复的索引值,然后从DataFrame中选择:

df2 = df.loc[df.index.repeat(df.n)]

  id  n   v
0  A  1  10
1  B  2  13
1  B  2  13
2  C  3   8
2  C  3   8
2  C  3   8

或者您可以使用np.repeat 来获取重复的索引,然后使用它来索引到框架中:

df2 = df.loc[np.repeat(df.index.values, df.n)]

  id  n   v
0  A  1  10
1  B  2  13
1  B  2  13
2  C  3   8
2  C  3   8
2  C  3   8

之后只需要进行一些清理工作:

df2 = df2.drop("n", axis=1).reset_index(drop=True)

  id   v
0  A  10
1  B  13
2  B  13
3  C   8
4  C   8
5  C   8

请注意,如果您可能需要担心重复的索引,您可以改用 .iloc:

df.iloc[np.repeat(np.arange(len(df)), df["n"])].drop("n", axis=1).reset_index(drop=True)

  id   v
0  A  10
1  B  13
2  B  13
3  C   8
4  C   8
5  C   8

它使用位置,而不是索引标签。

【讨论】:

  • 新版本可以df.loc[df.index.repeat(df.n)]
  • @zero:这应该是新接受的答案
【解决方案2】:

您可以使用set_index 和repeat

In [1057]: df.set_index(['id'])['v'].repeat(df['n']).reset_index()
Out[1057]:
  id   v
0  A  10
1  B  13
2  B  13
3  C   8
4  C   8
5  C   8

详情

In [1058]: df
Out[1058]:
  id  n   v
0  A  1  10
1  B  2  13
2  C  3   8

【讨论】:

    【解决方案3】:

    不是最好的解决方案,但我想分享一下:你也可以使用pandas.reindex() 和.repeat():

    df.reindex(df.index.repeat(df.n)).drop('n', axis=1)
    

    输出:

    
       id   v
    0   A   10
    1   B   13
    1   B   13
    2   C   8
    2   C   8
    2   C   8
    

    您可以进一步附加.reset_index(drop=True) 以重置.index。

    【讨论】:

      【解决方案4】:

      类似于tidyr 中的uncount:

      https://tidyr.tidyverse.org/reference/uncount.html

      我写了一个包 (https://github.com/pwwang/datar) 来实现这个 API:

      from datar import f
      from datar.tibble import tribble
      from datar.tidyr import uncount
      
      what_i_have = tribble(
          f.id, f.n, f.v,
          'A',  1,   10,
          'B',  2,   13,
          'C',  3,   8
      )
      what_i_have >> uncount(f.n)
      

      输出:

        id   v
      0  A  10
      1  B  13
      1  B  13
      2  C   8
      2  C   8
      2  C   8
      

      【讨论】:

        猜你喜欢
        • 2019-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多