【问题标题】:Pandas - Randomly Replace 10% of rows with other rowsPandas - 用其他行随机替换 10% 的行
【发布时间】:2018-04-24 08:45:30
【问题描述】:

我想在我的 df 中随机选择 10% 的所有行,并将每个行替换为 df 中随机抽样的现有行。

要随机选择 10% 的行 rows_to_change = df.sample(frac=0.1) 有效,我可以使用 replacement_sample = df.sample(n=1) 获得一个新的随机现有行,但我如何将它们放在一起以快速迭代整个 10%?

df 包含数百万行 x ~100 cols。

例子df:

df = pd.DataFrame({'A':[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],'B':[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],'C':[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]})

    A   B   C
0   1   1   1
1   2   2   2
2   3   3   3
3   4   4   4
4   5   5   5
5   6   6   6
6   7   7   7
7   8   8   8
8   9   9   9
9   10  10  10
10  11  11  11
11  12  12  12
12  13  13  13
13  14  14  14
14  15  15  15

假设它随机抽取索引 2,13 以替换为随机选择的索引 6,9,最终的 df 将如下所示:

    A   B   C
0   1   1   1
1   2   2   2
2   7   7   7
3   4   4   4
4   5   5   5
5   6   6   6
6   7   7   7
7   8   8   8
8   9   9   9
9   10  10  10
10  11  11  11
11  12  12  12
12  13  13  13
13  10  10  10
14  15  15  15

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以随机抽取一个样本,然后再抽取一个相同大小的随机样本,并将这些索引处的值替换为原始样本。

    import pandas as pd
    
    df = pd.DataFrame({'A': range(1,15), 'B': range(1,15), 'C': range(1,15)})
    
    samp = df.sample(frac=0.1)
    samp
    # returns:
        A   B   C
    6   7   7   7
    9  10  10  10
    
    replace = df.loc[~df.index.isin(samp.index)].sample(samp.shape[0])
    replace
    # returns:
       A  B  C
    3  4  4  4
    7  8  8  8
    
    df.loc[replace.index] = samp.values
    

    这会复制行而不替换

    df
    # returns:
         A   B   C
    0    1   1   1
    1    2   2   2
    2    3   3   3
    3    7   7   7
    4    5   5   5
    5    6   6   6
    6    7   7   7
    7   10  10  10
    8    9   9   9
    9   10  10  10
    10  11  11  11
    11  12  12  12
    12  13  13  13
    13  14  14  14
    14  15  15  15
    

    要进行替换采样,请在定义samp时使用关键字replace = True

    【讨论】:

      【解决方案2】:

      @James 的回答是一个聪明的 Pandas 解决方案。但是,鉴于您注意到您的数据集长度在数百万左右,您也可以考虑 NumPy,因为 Pandas 通常会带来显着的性能开销。

      def repl_rows(df: pd.DataFrame, pct: float):
          # Modifies `df` inplace.
          n, _ = df.shape
          rows = int(2 * np.ceil(n * pct))  # Total rows in both sets
          idx = np.arange(n, dtype=np.int)  # dtype agnostic
          full = np.random.choice(idx, size=rows, replace=False)
          to_repl, repl_with = np.split(full, 2)
          df.values[to_repl] = df.values[repl_with]
      

      步骤:

      • 以整数形式获取目标行。
      • 获取与索引长度相同的 NumPy 范围数组。如果您有不均匀的日期时间索引之类的东西,可能会比使用索引本身提供更多的稳定性。 (我不完全确定,可以玩弄。)
      • 此索引中的样本无需替换,样本大小是您要操作的行数的 2 倍。
      • 将结果分成两半以获得目标和替换。应该比两次调用choice() 更快。
      • 将位置to_repl 替换为repl_with 中的值。

      【讨论】:

        猜你喜欢
        • 2012-10-16
        • 2017-03-06
        • 1970-01-01
        • 1970-01-01
        • 2015-01-20
        • 2014-08-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多