【问题标题】:Replace values in dataframe column depending on another column with condition根据具有条件的另一列替换数据框列中的值
【发布时间】:2019-09-02 09:09:32
【问题描述】:

我需要替换数据框列 x 中的值。结果应该类似于 x_new。所以详细地说,我必须保留 x 列中 y 为 1 和 255 的值。在 1 和 255 之间,我必须用 y 为 1 的值替换 x 值。255 和 1 之间的值应该保持不变。那么如何获取 x_new 列呢?

我想它可以与替换和某些条件一起使用,但我不知道如何组合它。我期待任何帮助和提示。

我的数据框看起来像例如:

x        y    z    x_new
12.28   1    1     12.28
11.99   0    1     12.28
11.50   0    1     12.28
11.20   0    1     12.28
11.01   0    1     12.28
 9.74  255   0      9.74
13.80   0    0     13.80
15.2    0    0     15.2
17.8    0    0     17.8
12.1    1    1     12.1
11.9    0    1     12.1
11.7    0    1     12.1
11.2    0    1     12.1
10.3   255   0     10.3

【问题讨论】:

  • 您的数据是否足够干净,以至于在一行 1 之后总是跟着一行 255,然后是另一行 1?这使逻辑有点复杂
  • 是的,行是干净的,只有 1 到 255 之间的行数不同,这意味着有时有 4 行为零,有时例如50 或 100。感谢您的出色回答!

标签: python pandas dataframe replace


【解决方案1】:

多个步骤但有效。查找 y 为 255 的行的索引,直到找到下一个 1。将值保存在 idx 中。现在使用 idx 和其他两个条件(y == 1 或 y == 255)创建 new_x。完成剩下的。

# Index of rows between 255 and 1 in column y
idx = df.loc[df['y'].replace(0, np.nan).ffill() == 255, 'y'].index

# Create x_new1 and assign value of x where index is idx or y == 1 or y ==255
df.loc[idx, 'x_new1'] = df['x']
df.loc[(df['y'] == 1) | (df['y'] == 255) , 'x_new1'] = df['x']

# ffill rest of the values in x_new1
df['x_new1'] = df['x_new1'].ffill()


    x       y   z   x_new   x_new1
0   12.28   1   1   12.28   12.28
1   11.99   0   1   12.28   12.28
2   11.50   0   1   12.28   12.28
3   11.20   0   1   12.28   12.28
4   11.01   0   1   12.28   12.28
5   9.74    255 0   9.74    9.74
6   13.80   0   0   13.80   13.80
7   15.20   0   0   15.20   15.20
8   17.80   0   0   17.80   17.80
9   12.10   1   1   12.10   12.10
10  11.90   0   1   12.10   12.10
11  11.70   0   1   12.10   12.10
12  11.20   0   1   12.10   12.10
13  10.30   255 0   10.30   10.30

【讨论】:

    【解决方案2】:

    假设 1 和 255 总是成对出现的干净数据,我们可以将 1-255 和 groupby 组成分组来填充数据。

    s = (df.y.eq(1).cumsum() == df.y.eq(255).cumsum()+1)
    df['xnew'] = df.groupby(s.ne(s.shift()).cumsum().where(s)).x.transform('first').fillna(df.x)
    
            x    y  z   xnew
    0   12.28    1  1  12.28
    1   11.99    0  1  12.28
    2   11.50    0  1  12.28
    3   11.20    0  1  12.28
    4   11.01    0  1  12.28
    5    9.74  255  0   9.74
    6   13.80    0  0  13.80
    7   15.20    0  0  15.20
    8   17.80    0  0  17.80
    9   12.10    1  1  12.10
    10  11.90    0  1  12.10
    11  11.70    0  1  12.10
    12  11.20    0  1  12.10
    13  10.30  255  0  10.30
    

    尽管对于这样的事情,你真的应该形成一个彻底的单元测试,因为这个逻辑可能会因为输入不正确而变得非常棘手和有问题。

    【讨论】:

      【解决方案3】:

      试试:

      # mark the occurrences of 1 and 255
      df['is_1_255'] = df.y[(df.y==1)|(df.y==255)]
      df['x_n'] = None
      
      # copy the 1's 
      df.loc[df.is_1_255==1,'x_n'] = df.loc[df.is_1_255==1,'x']
      
      # fill is_1_255 with markers, 
      #255 means between 255 and 1, 1 means between 1 and 255
      df['is_1_255'] = df['is_1_255'].ffill()
      
      # update the 255 values
      df.loc[df.is_1_255==255, 'x_n'] = df.loc[df.is_1_255==255,'x']
      
      # update the 1 values
      df['x_n'].ffill(inplace=True)
      

      输出:

      +-----+-------+-----+---+-------+----------+-------+
      | idx |   x   |  y  | z | x_new | is_1_255 |  x_n  |
      +-----+-------+-----+---+-------+----------+-------+
      |   0 | 12.28 |   1 | 1 | 12.28 | 1.0      | 12.28 |
      |   1 | 11.99 |   0 | 1 | 12.28 | 1.0      | 12.28 |
      |   2 | 11.50 |   0 | 1 | 12.28 | 1.0      | 12.28 |
      |   3 | 11.20 |   0 | 1 | 12.28 | 1.0      | 12.28 |
      |   4 | 11.01 |   0 | 1 | 12.28 | 1.0      | 12.28 |
      |   5 | 9.74  | 255 | 0 | 9.74  | 255.0    | 9.74  |
      |   6 | 13.80 |   0 | 0 | 13.80 | 255.0    | 13.80 |
      |   7 | 15.20 |   0 | 0 | 15.20 | 255.0    | 15.20 |
      |   8 | 17.80 |   0 | 0 | 17.80 | 255.0    | 17.80 |
      |   9 | 12.10 |   1 | 1 | 12.10 | 1.0      | 12.10 |
      |  10 | 11.90 |   0 | 1 | 12.10 | 1.0      | 12.10 |
      |  11 | 11.70 |   0 | 1 | 12.10 | 1.0      | 12.10 |
      |  12 | 11.20 |   0 | 1 | 12.10 | 1.0      | 12.10 |
      |  13 | 10.30 | 255 | 0 | 10.30 | 255.0    | 10.30 |
      +-----+-------+-----+---+-------+----------+-------+
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-18
        • 1970-01-01
        • 2022-07-30
        • 2019-01-31
        • 1970-01-01
        • 1970-01-01
        • 2012-11-06
        • 2021-10-01
        相关资源
        最近更新 更多