同时迭代两列并根据条件更改单元格的值
Iterate over two columns at the same time and change value of cells based on conditions
我有以下格式的数据框:
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
它继续对象 3、对象 4 等等...
我想通过以下方式同时检查两列:
if ObjectX-Length >= 20 and ObjectX-Height >= 50
然后将 ObjectX 的两个单元格设置为 1,否则将它们设置为 0
这就是我想要的table:
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 也可以!
不太优雅的方式:
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)
让我们试试:
# 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
详情:
首先filter
Length
类列,然后创建相应的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
您可以在删除 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
您可以从 numpy
和 reshape
获得帮助。
使用 reshape
您可以将每一对“移动”到临时的第 3 维,然后您可以拥有一个自然行,其中包含您要比较的“有趣”列。
在此之后,您可以恢复原始数据框形状的重塑。
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
我有以下格式的数据框:
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 |
它继续对象 3、对象 4 等等...
我想通过以下方式同时检查两列:
if ObjectX-Length >= 20 and ObjectX-Height >= 50
然后将 ObjectX 的两个单元格设置为 1,否则将它们设置为 0
这就是我想要的table:
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 也可以!
不太优雅的方式:
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)
让我们试试:
# 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
详情:
首先filter
Length
类列,然后创建相应的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
您可以在删除 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
您可以从 numpy
和 reshape
获得帮助。
使用 reshape
您可以将每一对“移动”到临时的第 3 维,然后您可以拥有一个自然行,其中包含您要比较的“有趣”列。
在此之后,您可以恢复原始数据框形状的重塑。
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