【问题标题】:Iterate over two columns at the same time and change value of cells based on conditions同时迭代两列并根据条件更改单元格的值
【发布时间】:2021-01-02 15:28:32
【问题描述】:

我有一个格式如下的数据框:

Index Object1-Length Object1-Height Object2-Length Object2-Height
0 19 49 21 52
1 20 50 21 51
2 20 51 20 52
3 19 50 19 52
4 20 50 20 52

它继续 Object3、Object4 等等......

我想通过以下方式同时检查两列:

if ObjectX-Length >= 20 and ObjectX-Height >= 50 

然后将 ObjectX 的两个单元格设置为 1,否则将它们设置为 0

这就是我想要的表格:

Index Object1-Length Object1-Height Object2-Length Object2-Height
0 0 0 1 1
1 1 1 1 1
2 1 1 1 1
3 0 0 0 0
4 1 1 1 1

有什么办法吗?

编辑:将每个对象的两列合并为一列并将该单元格设置为 0 或 1 也可以!

【问题讨论】:

    标签: python pandas dataframe multiple-columns


    【解决方案1】:

    让我们试试吧:

    # length like columns
    l = df.filter(like='-Length').columns
    
    # corresponding height columns
    h = l.str.rstrip('Length') + 'Height'
    
    # create boolean mask
    m = (df[l].ge(20).values & df[h].ge(50).values).astype(int)
    
    # assign the values
    df[h], df[l] = m, m
    

    详情:

    首先filterLengthlike列,然后创建对应的Height列:

    print(l)
    ['Object1-Length', 'Object2-Length']
    
    print(h)
    ['Object1-Height', 'Object2-Height']
    

    创建表示ObjectX-Length >= 20 and ObjectX-Height >= 50: 的条件的布尔掩码

    print(m)
    array([[0, 1],
           [1, 1],
           [1, 1],
           [0, 0],
           [1, 1]])
    

    将掩码分配给相应的列:

    print(df)
           Object1-Length  Object1-Height  Object2-Length  Object2-Height
    Index                                                                
    0                   0               0               1               1
    1                   1               1               1               1
    2                   1               1               1               1
    3                   0               0               0               0
    4                   1               1               1               1
    

    【讨论】:

      【解决方案2】:

      您可以从numpyreshape 获得帮助。 使用reshape,您可以将每一对“移动”到一个临时的第三维,然后您可以拥有一个包含您想要比较的“有趣”列的自然行。

      在此之后,您可以恢复原始数据框形状的重塑。

      import pandas as pd
      import numpy as np
      
      # example dataset
      df = pd.DataFrame(np.random.randint(100, size=(8, 6)), columns = ['A-L', 'A-H', 'B-L', 'B-H', 'C-L', 'C-H'])
      
      m, n = df.shape
      data = df.values
      
      data = data.reshape((m, 2, -1), order='F')
      cond = (data[:,(0,),:] >= 20) & (data[:,(1,),:] >= 50)
      new_data = np.repeat(cond, 2, axis=1)
      new_data = new_data.reshape((m, -1), order='F')
      new_df = pd.DataFrame(new_data, columns=df.columns)
      
      print(df)
      print(new_df)
      
      
         A-L  A-H  B-L  B-H  C-L  C-H
      0   36   99    0   65   44   41
      1   31   52    7   33   27   80
      2   39   89   57   18   72   76
      3    4   13   11   38   21    9
      4   72    4    9   16   78   96
      5   26   79   80   53   36   81
      6   81   59   93   49   39   24
      7   45   49   52   54   63   70
      
           A-L    A-H    B-L    B-H    C-L    C-H
      0   True   True  False  False  False  False
      1   True   True  False  False   True   True
      2   True   True  False  False   True   True
      3  False  False  False  False  False  False
      4  False  False  False  False   True   True
      5   True   True   True   True   True   True
      6   True   True  False  False  False  False
      7  False  False   True   True   True   True
      

      【讨论】:

        【解决方案3】:

        不太优雅的方式:

        r = [] 
        for n in range(1, x): # where x = maximum X + 1 
            len_col = f'Object{n}-Length'
            height_col = f'Object{n}-Height'
        
            # create filter mask for current object {n}
            subset = df[[len_col, height_col]]
            msk = (df[len_col] >= 20) & (df[height_col] >= 50)
        
            subset.loc[msk,[len_col, height_col] = 1 
            subset.loc[~msk,[len_col, height_col] = 0 
            r.append(subset)
        
        
        r = pd.concat(r)
        

        【讨论】:

        • 非常感谢您的回复!我从未使用过过滤面具,它究竟是如何工作的?
        • 它基本上只是返回一个与df具有相同形状的布尔数组;当您执行df[msk] 时,它仅返回 msk 中为 True 的值。
        • 我明白了,谢谢!两个问题:第一:不是每个对象都在数据框中,例如,没有 Object5 但有一个 Object6 等......我该如何解释这个?第二:它在第一个对象之后以某种方式停止并且没有遍历范围内的所有对象,这可能是什么原因?
        • 让它工作,非常感谢您的回复!
        【解决方案4】:

        您可以在删除Index 列后一次过滤所有列。然后groupyby 每两列都设置为False,如果至少有一个是False

        df.set_index('Index', inplace=True)
        df.ge([20,50]*(df.columns.size//2)).groupby(np.arange(df.columns.size)//2, axis=1).transform('min').astype('int')
        

        输出:

               Object1-Length  Object1-Height  Object2-Length  Object2-Height
        Index                                                                
        0                   0               0               1               1
        1                   1               1               1               1
        2                   1               1               1               1
        3                   0               0               0               0
        4                   1               1               1               1
        

        【讨论】:

          猜你喜欢
          • 2021-05-21
          • 1970-01-01
          • 2021-09-11
          • 2017-11-23
          • 2023-03-18
          • 1970-01-01
          • 1970-01-01
          • 2021-09-29
          • 2013-10-23
          相关资源
          最近更新 更多