循环遍历DataFrame列修改切片时部分列未生效的问题
问题原因
循环执行时,先处理了employment列,将符合条件的行的employment值从'12-15'改成了'12'。当后续遍历到country和city列时,df['employment']=='12-15'的筛选条件已经不成立,导致这两列的目标行没有被修改。
修复方案
方案1:提前保存筛选条件(推荐)
先计算出需要修改的行的掩码(mask),后续循环直接使用这个固定的掩码,避免因修改employment列导致条件失效:
data = {'id':[12, 84, 156, 228, 300, 372, 444, 516, 588, 660, 732], 'age':['18-18', '22-22', '35-35', '33-33', '45-45', '40-40', '55-55', '60-60', '47-47', '25-25', '59-59'], 'height':['175-177', '165-167', '175-178', '165-168', '175-179', '165-169', '175-180', '165-170', '175-181', '165-171', '175-182'], 'weight':['65-70', '65-70', '80-85', '75-80', '90-95', '100-105', '80-85', '70-75', '70-75', '85-90', '90-95'], 'education':['10-12', '11-13', '12-14', '13-15', '14-16', '15-17', '16-18', '17-19', '18-20', '19-21', '20-22'], 'employment':['1-4', '8-11', '8-11', '4-7', '5-8', '5-8', '9-12', '15-18', '13-16', '12-15', '12-15'], 'country':['France-EU', 'Austria-EU', 'Netherland-EU', 'Italy-EU', 'Texas-US', 'California-US', 'Washington-US', 'Poland-EU', 'Spain-EU', 'Greece-EU', 'New York-US'], 'city':['Paris-FR', 'Vienna-AUS', 'Amsterdam-NL', 'Rome-ITA', 'Austin-TX', 'LA-CAL', 'Olympia-WAS', 'Warsaw-PL', 'Madrid-SPA', 'Athens-GR', 'Albany-NY']} df = pd.DataFrame(data) # 提前保存需要修改的行的筛选条件 mask = df['employment'] == '12-15' for col in df.columns: if col == 'id': continue # 使用固定的mask筛选行 df.loc[mask, col] = df[col].str.split('-').str[0]
方案2:调整列的遍历顺序
先处理除employment外的其他列,最后再修改employment列,这样前面列修改时筛选条件仍然有效:
data = {'id':[12, 84, 156, 228, 300, 372, 444, 516, 588, 660, 732], 'age':['18-18', '22-22', '35-35', '33-33', '45-45', '40-40', '55-55', '60-60', '47-47', '25-25', '59-59'], 'height':['175-177', '165-167', '175-178', '165-168', '175-179', '165-169', '175-180', '165-170', '175-181', '165-171', '175-182'], 'weight':['65-70', '65-70', '80-85', '75-80', '90-95', '100-105', '80-85', '70-75', '70-75', '85-90', '90-95'], 'education':['10-12', '11-13', '12-14', '13-15', '14-16', '15-17', '16-18', '17-19', '18-20', '19-21', '20-22'], 'employment':['1-4', '8-11', '8-11', '4-7', '5-8', '5-8', '9-12', '15-18', '13-16', '12-15', '12-15'], 'country':['France-EU', 'Austria-EU', 'Netherland-EU', 'Italy-EU', 'Texas-US', 'California-US', 'Washington-US', 'Poland-EU', 'Spain-EU', 'Greece-EU', 'New York-US'], 'city':['Paris-FR', 'Vienna-AUS', 'Amsterdam-NL', 'Rome-ITA', 'Austin-TX', 'LA-CAL', 'Olympia-WAS', 'Warsaw-PL', 'Madrid-SPA', 'Athens-GR', 'Albany-NY']} df = pd.DataFrame(data) # 先遍历除employment外的列 for col in [col for col in df.columns if col not in ['id', 'employment']]: df.loc[df['employment']=='12-15', col] = df[col].str.split('-').str[0] # 最后修改employment列 df.loc[df['employment']=='12-15', 'employment'] = df['employment'].str.split('-').str[0]
方案3:批量处理(更高效)
利用pandas的批量操作替代循环,代码更简洁且效率更高:
data = {'id':[12, 84, 156, 228, 300, 372, 444, 516, 588, 660, 732], 'age':['18-18', '22-22', '35-35', '33-33', '45-45', '40-40', '55-55', '60-60', '47-47', '25-25', '59-59'], 'height':['175-177', '165-167', '175-178', '165-168', '175-179', '165-169', '175-180', '165-170', '175-181', '165-171', '175-182'], 'weight':['65-70', '65-70', '80-85', '75-80', '90-95', '100-105', '80-85', '70-75', '70-75', '85-90', '90-95'], 'education':['10-12', '11-13', '12-14', '13-15', '14-16', '15-17', '16-18', '17-19', '18-20', '19-21', '20-22'], 'employment':['1-4', '8-11', '8-11', '4-7', '5-8', '5-8', '9-12', '15-18', '13-16', '12-15', '12-15'], 'country':['France-EU', 'Austria-EU', 'Netherland-EU', 'Italy-EU', 'Texas-US', 'California-US', 'Washington-US', 'Poland-EU', 'Spain-EU', 'Greece-EU', 'New York-US'], 'city':['Paris-FR', 'Vienna-AUS', 'Amsterdam-NL', 'Rome-ITA', 'Austin-TX', 'LA-CAL', 'Olympia-WAS', 'Warsaw-PL', 'Madrid-SPA', 'Athens-GR', 'Albany-NY']} df = pd.DataFrame(data) mask = df['employment'] == '12-15' # 选择需要修改的列(排除id) cols_to_modify = df.columns.drop('id') # 批量分割字符串并取第一个元素 df.loc[mask, cols_to_modify] = df.loc[mask, cols_to_modify].apply(lambda x: x.str.split('-').str[0])
内容的提问来源于stack exchange,提问作者Brandon
相关产品推荐
相关产品推荐

