提问人:user3641630 提问时间:9/15/2023 最后编辑:user3641630 更新时间:9/15/2023 访问量:71
Python 中的函数,用于遍历列并在满足条件时替换值
function in python to loop through columns and replace values if condition is met
问:
我想创建一个计算列 A-C 的函数。如果行值为 Type,后跟 A、B、C,则将这些列中的值替换为 “”。如果替换了一个值,我想创建一个名为“Replaced”=1 的列。
下面是创建 df 的代码和我编写的函数。我想知道我在这个功能中做错了什么?有人可以帮我吗?
import pandas as pd
df = pd.DataFrame(
{
'ID': ['1','2','3','4','5'],
'Values': [57, 98, 87, 69, 98],
'A': ['Type', 'Type', 'Type', 'Type', 'Type'],
'B': ['A', 'B', 'Type', 'Type', 'Type'],
'C': ['B', 'B','A', 'Type', 'C']
}
)
df
#function I wrote:
cols=['A','B','C']
def fix_type(self):
for i in range(len(cols) - 1):
if cols[i] == 'Type' and cols[i+1] in ['A', 'B', 'C']:
cols[i] = ''
cols[i+1] = ''
Replaced = 1
df[cols].apply(fix_type)
df
上面的函数没有给出我想要的结果。结果如下所示:如上所述,如果 Type 后面跟着 A、B、C,我想用 “” #replace “Type” 和后面的 A/B/C。
df_result=pd.DataFrame(
{
'ID': ['1','2','3','4','5'],
'Values': [57, 98, 87, 69, 98],
'A': ['', '', 'Type', 'Type', 'Type'],
'B': ['', '','', 'Type', ''],
'C': ['B', 'B','', 'Type', ''],
'Replaced': [1, 1,1,0, 1]
}
)
df_result
答:
0赞
RomanPerekhrest
9/15/2023
#1
1)具有自定义更换功能:
def replace_type_pair(s):
abc_cols = s[:-1] # (A, B, C) columns
idx = ((abc_cols.eq('Type') & abc_cols.shift(-1).isin(abc_cols.index))
.values.nonzero()[0]) # index of 'Type' value conditioned
if idx.size:
s[idx[0]: idx[0] + 2] = '' # reset 'Type' and the value next to it
s['Replaced'] = 1
return s
df['Replaced'] = 0
cols = ['A', 'B', 'C', 'Replaced']
df.loc[:, cols] = (df[cols].apply(replace_type_pair, axis=1))
print(df)
ID Values A B C Replaced
0 1 57 B 1
1 2 98 B 1
2 3 87 Type 1
3 4 69 Type Type Type 0
4 5 98 Type 1
或
2) 使用布尔掩码和基于初步发现/计算的索引对匹配行的遍历:
cols = ['A', 'B', 'C']
df['Replaced'] = 0
m = (df[cols].eq('Type', axis=1) & df[cols].shift(-1, axis=1).isin(cols))
idx = np.argwhere(m.values)
df.loc[idx[:, 0], 'Replaced'] = 1
for row, col in idx:
df.loc[row, cols[col: col + 2]] = ''
print(df)
评论
0赞
user3641630
9/15/2023
谢谢!作为 python 的新手,我学到了一些新东西。
0赞
RomanPerekhrest
9/15/2023
@user3641630,欢迎,检查我的第二种方法,它对你来说可能更有效率
1赞
user3641630
9/15/2023
谢谢 - 非常感谢。
0赞
Timeless
9/15/2023
#2
另一种可能的解决方案:
tmp = df[cols]
N = 1 # "OP: immediately followed"
m1 = tmp.mask(tmp.eq("Type")).bfill(axis=1, limit=N).isnull()
m2 = tmp.shift(axis=1, fill_value="Type").ne("Type")
out = (
df[df.columns.difference(cols)].join(tmp.where(m1|m2, ""))
.assign(Replaced=(~(m1^m2).all(axis=1)).astype(int))
)
输出:
print(out)
ID Values A B C Replaced
0 1 57 B 1
1 2 98 B 1
2 3 87 Type 1
3 4 69 Type Type Type 0
4 5 98 Type 1
评论
'','','B'