同时迭代两列并根据条件更改单元格的值

3

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

索引 对象1-长度 对象1-高度 对象2-长度 对象2-高度
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,则将它们设置为 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 也可以。
4个回答

6

让我们来试试:

# 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

详情:

首先像列一样筛选长度,然后创建相应的高度列:

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
在删除“Index”列之后,您可以一次性过滤所有列。然后使用groupby函数将每两个列进行分组,如果至少有一个列为False,则将这两个列都设置为False。请注意保留HTML标签。
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

2

不太优雅的方式:

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)

非常感谢您的回复!我从未使用过过滤器掩码,它究竟是如何工作的? - pyth_qwertz
它基本上只返回一个布尔数组,该数组与df具有相同的形状;当您执行df [msk]时,它仅返回在msk中为True的值。 - ABC
我明白了,谢谢!有两个问题: 第一个:并不是每个对象都在数据框中,例如没有Object5,但有Object6等等... 我该如何处理? 第二个:它在第一个对象之后就停止了,而且没有遍历范围内的所有对象,这可能是什么原因? - pyth_qwertz
1
成功了,非常感谢您的回复! - pyth_qwertz

2
你可以使用numpyreshape来获得帮助。使用reshape可以将每一对数据移动到一个临时的第三维度,然后你就可以有自然的行来包含你想要比较的“有趣”列。
之后,你可以将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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接