Python 如何迭代数据帧的所有行,将查找函数应用于字符串值,并将结果应用于新列?
我有一个数据框,每行(个人)有几列个人数据。我想应用一个函数在区域列表中查找每个人的城市或州,然后将结果应用到同一数据框中的新列“Region” 我已经能够使用一个非常简化的数据框,对颜色和车辆进行分类,从而实现相同的操作(见下文)。但当我尝试使用个人数据时,它不会以同样的方式工作,我不明白为什么 我已经阅读了很多关于lambda函数的thead,但是我认为我要问的太复杂了。大多数解决方案处理数值数据,我使用字符串,但正如我所说的,我能够使用一个数据集。显然我是新来的。我也希望你能给我一些建议,告诉我如何把新专栏作为函数的一部分来构建,而不是把它作为一个单独的步骤来构建,但这并不像主要问题那样让我沮丧 此示例适用于: 测向显示器:Python 如何迭代数据帧的所有行,将查找函数应用于字符串值,并将结果应用于新列?,python,pandas,function,Python,Pandas,Function,我有一个数据框,每行(个人)有几列个人数据。我想应用一个函数在区域列表中查找每个人的城市或州,然后将结果应用到同一数据框中的新列“Region” 我已经能够使用一个非常简化的数据框,对颜色和车辆进行分类,从而实现相同的操作(见下文)。但当我尝试使用个人数据时,它不会以同样的方式工作,我不明白为什么 我已经阅读了很多关于lambda函数的thead,但是我认为我要问的太复杂了。大多数解决方案处理数值数据,我使用字符串,但正如我所说的,我能够使用一个数据集。显然我是新来的。我也希望你能给我一些建议,
one two three type
0 1 A car
1 2 B bus
2 3 C red
3 4 D blue
4 5 E truck
5 6 F pencil
6 7 G yellow
7 8 H green
Last Name First Name Code Deparment City State Region
0 SMITH TOM 12 Research NEW YORK NY
1 JONES DICK 34 Management BOSTON MA
2 WILSON HARRY 56 Maintenance SAN FRANCISCO CA
3 DOYLE MICHAEL 78 Marketing DALLAS TX
4 ANDERSON KEVIN 90 IT DETROIT MI
现在定义列表和自定义函数:
# Definte lists of colors and vehicles
colors = ['red','blue','green','yellow']
vehicles = ['car','truck','bus','motorcycle']
# Create function 'celltype' to return values based on x
def celltype (x):
if x in colors: return 'color'
elif x in vehicles: return 'vehicle'
else: return 'other'
# Write loop to iterate through df rows and apply function 'celltype' to column 'three' in each row
for index, row in df.iterrows():
row['type'] = celltype(row['three'])
然后构造一个循环,遍历每一行并应用函数:
# Definte lists of colors and vehicles
colors = ['red','blue','green','yellow']
vehicles = ['car','truck','bus','motorcycle']
# Create function 'celltype' to return values based on x
def celltype (x):
if x in colors: return 'color'
elif x in vehicles: return 'vehicle'
else: return 'other'
# Write loop to iterate through df rows and apply function 'celltype' to column 'three' in each row
for index, row in df.iterrows():
row['type'] = celltype(row['three'])
在这种情况下,结果正是我想要的:
one two three type
0 1 A car vehicle
1 2 B bus vehicle
2 3 C red color
3 4 D blue color
4 5 E truck vehicle
5 6 F pencil other
6 7 G yellow color
7 8 H green color
这个例子不起作用,我不知道为什么: df1显示:
one two three type
0 1 A car
1 2 B bus
2 3 C red
3 4 D blue
4 5 E truck
5 6 F pencil
6 7 G yellow
7 8 H green
Last Name First Name Code Deparment City State Region
0 SMITH TOM 12 Research NEW YORK NY
1 JONES DICK 34 Management BOSTON MA
2 WILSON HARRY 56 Maintenance SAN FRANCISCO CA
3 DOYLE MICHAEL 78 Marketing DALLAS TX
4 ANDERSON KEVIN 90 IT DETROIT MI
同样,定义列表和函数:
# Define lists for regions
east = ['NEW YORK','BOSTON']
west = ['SAN FRANCISCO','LOS ANGELES']
south = ['TX']
# Create function 'region' to return values based on x
def region (x):
if x in east: return 'east'
elif x in west: return 'west'
elif x in south: return 'south'
else: return 'other'
# Write loop to iterate through df1 rows and apply function 'region' to column 'City' in each row
for index, row in df1.iterrows():
row['Region'] = region(row['City'])
if row['Region'] == 'other': row['Region'] = region(row['State'])
这将导致df1保持不变。“区域”列仍然为空。我们应该看到“东”、“东”、“西”、“南”、“其他”。代码中唯一的区别是附加的“if”语句,用于按州捕获Dallas(这是我的真实数据集所需要的)。但是我认为这行代码是正确的,没有它我也能得到同样的结果。首先,
apply
和iterrows
都很慢,所以永远不要使用它们
在这种情况下,我通常会创建一对向前
和向后
指令:
forward = {'east': east,
'west': west,
'south': south}
backward = {x:k for k,v in forward.items() for x in v}
然后使用map
进行更新。由于您希望基于两列进行更新,fillna
将非常有用:
df1['Region'] = (df1['State'].map(backward)
.fillna(df1['City'].map(backward))
.fillna('other')
)
给出:
Last Name First Name Code Deparment City State Region
0 SMITH TOM 12 Research NEW YORK NY east
1 JONES DICK 34 Management BOSTON MA east
2 WILSON HARRY 56 Maintenance SAN FRANCISCO CA west
3 DOYLE MICHAEL 78 Marketing DALLAS TX south
4 ANDERSON KEVIN 90 IT DETROIT MI other
您的问题在于如何使用
iterrows
。通常,您不应该修改正在迭代的内容。在这种情况下,iterrows
正在创建数据的副本,因此实际上没有修改df1
。复制可能会发生,也可能不会发生,这取决于具体情况,所以像这样的事情通常是您希望避免做的
您可以通过在处直接调用数据帧来确保它修改了原始数据帧:
for index, row in df1.iterrows():
df1.at[index, 'Region'] = region(row['City'])
if df1.at[index, 'Region'] == 'other': df1.at[index, 'Region'] = region(row['State'])
非常感谢。这完全奏效了,而且就你的观点而言,它更快,即使使用真实世界的数据。对我来说,倒着念是个新把戏。谢谢你的提示,这是个好提示。iterrows代码使用一个数据集而不使用另一个数据集,这让我很困惑,但我想这是不可预测的。当我使用它时,我通过删除“Code”列使df1数据集工作。关于它的某些东西可能偶然发现了数字数据?但无论哪种方式,选择的答案都可能是一种比最初使用iterrows更好的方法。谢谢你的帮助。@WilliamCollins没问题。改变某些东西可能会使它工作,但由于你做它的方式的不可预测性,你仍然不想这样做,因为它可能并不总是工作。我的回答是试图向你解释为什么你的代码不起作用。但是,另一种解决方案肯定更快,而且可能更好。