【问题标题】:replicate rows by n times in python在python中将行复制n次
【发布时间】:2022-02-09 05:36:28
【问题描述】:

我有一个数据框,第一列是字符串,第二列是我想要复制每个字符串的数字。

df = pd.DataFrame({'String':['a','b', 'c', 'd', 'e', 'f', 'g'],
        'Times':[2, 3, 5, 3, 2, 4, 5]})
df
String Times
a 2
b 3
c 5
d 3
e 2
f 4
g 5

如何在 python 中创建一个数据框? (停在 d 但你知道模式)。谢谢!

String Times
a 1
a 2
b 1
b 2
b 3
c 1
c 2
c 3
c 4
c 5

【问题讨论】:

标签: python pandas


【解决方案1】:

另一种方法可能是:

df.assign(Times = df.Times.apply(lambda x: range(1, x + 1))).explode('Times')
Out[]: 
  String Times
0      a     1
0      a     2
1      b     1
1      b     2
1      b     3
2      c     1
2      c     2
2      c     3
2      c     4
2      c     5

【讨论】:

    【解决方案2】:

    有点乱,但似乎做你想做的事:

    new_df = pd.DataFrame(df.String.str.repeat(df.Times).apply(list).explode().reset_index(drop=True))
    
    new_df["Times"] = new_df.groupby("String").cumcount() + 1
    

    输出:

       String  Times
    0       a      1
    1       a      2
    2       b      1
    3       b      2
    4       b      3
    5       c      1
    6       c      2
    7       c      3
    8       c      4
    9       c      5
    10      d      1
    11      d      2
    12      d      3
    13      e      1
    14      e      2
    15      f      1
    16      f      2
    17      f      3
    18      f      4
    19      g      1
    20      g      2
    21      g      3
    22      g      4
    23      g      5
    

    【讨论】:

    • 老实说我的表现最差。可能是因为创建了新的 DataFrame?
    【解决方案3】:

    使用Index.repeat 复制行并使用groupby+cumcount: 枚举它们:

    (df.loc[df.index.repeat(df['Times'])]
       .assign(Times=lambda d: d.groupby('String').cumcount().add(1))
     )
    

    输出:

      String  Times
    0      a      1
    0      a      2
    1      b      1
    1      b      2
    1      b      3
    2      c      1
    2      c      2
    2      c      3
    2      c      4
    2      c      5
    3      d      1
    ...
    
    所有答案的比较(7k 行):
    @mozway
    11.2 ms ± 1.63 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
    
    @Onyambu
    16 ms ± 685 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    
    @ifly6
    27.3 ms ± 2.42 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    @ddejohn
    28.5 ms ± 4.2 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    

    在 700k 行上:1s, 1.43s, 2.34s, 2.94s 以相同的顺序

    【讨论】:

      【解决方案4】:

      使用df.explode。通过将您的重复转换为列表来完成这项工作:

      s = ['a','b', 'c', 'd', 'e', 'f', 'g']
      t = [2, 3, 5, 3, 2, 4, 5]
      

      那么,

      times = [list(range(i + 1)) for i in t]
      df = pd.DataFrame({'string': s, 'times': times}).explode('times')
      
      >>> df.head(10)
        string times
      0      a     0
      0      a     1
      0      a     2
      1      b     0
      1      b     1
      1      b     2
      1      b     3
      2      c     0
      2      c     1
      2      c     2
      

      如果您不希望索引像那样重复,df.reset_index(drop=True, inplace=True)(如果存在,则重新分配)。如果您想要 1-indexing 而不是 0-indexing,请为 list(range(i + 1)) 替换 list(range(1, i + 2))。或者,只需在末尾的times 列中添加一个。 times 列对 df.explode 来说并不重要,无论如何它都会根据重复而爆炸。

      【讨论】:

        猜你喜欢
        • 2020-01-26
        • 2019-09-29
        • 2013-10-24
        • 2012-08-04
        • 1970-01-01
        • 1970-01-01
        • 2018-07-21
        • 1970-01-01
        • 2017-09-27
        相关资源
        最近更新 更多