如何使用python2.7使用嵌套for循环遍历数据帧并附加到新的数据帧列?
我尝试遍历两个python dataframe列以确定特定值,然后将结果添加到一个新列中。下面的代码引发以下错误:如何使用python2.7使用嵌套for循环遍历数据帧并附加到新的数据帧列?,python,python-2.7,pandas,dataframe,Python,Python 2.7,Pandas,Dataframe,我尝试遍历两个python dataframe列以确定特定值,然后将结果添加到一个新列中。下面的代码引发以下错误: raise ValueError('Length of values does not match length of ' 'index')" 我不知道为什么 数据帧: TeamID todayorno 1 sw True 2 pr False 3 sw False 4 pr True 代码
raise ValueError('Length of values does not match length of ' 'index')"
我不知道为什么
数据帧:
TeamID todayorno
1 sw True
2 pr False
3 sw False
4 pr True
代码:
您正在迭代数据帧两次,这表明您有2个
for
循环。最终得到的结果是10项,而不是所需的4项
不需要显式迭代。您可以使用numpy。选择为指定条件应用值
import numpy as np
mask = results['TeamID'] == 'sw'
conditions = [~mask, mask & results['todayorno'], mask & ~results['todayorno']]
values = ['green', 'red', 'green']
results['newnew'] = np.select(conditions, values, 'green')
print(results)
TeamID todayorno newnew
1 sw True red
2 pr False green
3 sw False green
4 pr True green
快速回答
不要试图循环
相反,使用默认值(即最常见值)创建新列,然后处理要更改的值并进行设置:
>>> results
TeamID todayorno
0 sw True
1 pr False
2 sw False
3 pr True
>>> results['newnew'] = 'green'
>>> results
TeamID todayorno newnew
0 sw True green
1 pr False green
2 sw False green
3 pr True green
>>> results.loc[(results['TeamID'] == 'sw') & (results['todayorno']), 'newnew'] = 'red'
>>> results
TeamID todayorno newnew
0 sw True red
1 pr False green
2 sw False green
3 pr True green
或者,您可以使用.apply(…,index=1)
使用查看每行的函数计算整个系列,并将整个系列一次性指定为列:
>>> results
TeamID todayorno
0 sw True
1 pr False
2 sw False
3 pr True
>>> results['newnew'] = results.apply(
... lambda s: 'red' if s['TeamID'] == 'sw' and s['todayorno'] else 'green',
... axis=1,
... )
>>> results
TeamID todayorno newnew
0 sw True red
1 pr False green
2 sw False green
3 pr True green
解释
问题
从您的代码中可以看出,您正在尝试向数据帧添加一个名为newnew
的列
在数据框的行中,TeamID
列包含值“sw”
,列todayorno
包含值True
,您希望列newnew
包含值“red”
在所有其他行中,您希望newnewnew
的值为“绿色”
规矩
为了有效地与熊猫合作,一条非常重要的规则是:不要试图循环。尤其是穿过一排排
相反,让熊猫为你做这项工作
因此,第一步是创建新列。由于在大多数情况下,您希望值为“绿色”
,因此只需执行以下操作:
results['newnew'] = 'green'
现在,您的数据帧看起来像:
TeamID todayorno newnew
0 sw True green
1 pr False green
2 sw False green
3 pr True green
您会注意到熊猫“扩展”了所有行中提供的单个值
现在要将sw/True
行设置为“红色”
,首先需要找到所有行。为此,我们需要了解熊猫是如何工作的
(一点点)熊猫如何工作
当在数据帧后使用方括号时,通常是在对数据帧的列进行寻址。例:
>>> results['TeamID']
0 sw
1 pr
2 sw
3 pr
Name: TeamID, dtype: object
也就是说,通过请求TeamID
数据帧的results
索引,您得到了一个名为TeamID
的系列,其中只包含该列的值
另一方面,如果要寻址行,则需要使用.loc
属性
>>> results.loc[1]
TeamID pr
todayorno False
newnew green
Name: 1, dtype: object
这里我们得到了一个系列
,其中包含该行的值
如果我们想看到多行,我们可以通过索引行列表来获得子数据帧:
>>> results.loc[[1,2]]
TeamID todayorno newnew
1 pr False green
2 sw False green
或者通过使用条件:
>>> results.loc[results['TeamID'] == 'pr']
TeamID todayorno newnew
1 pr False green
3 pr True green
条件可以包含布尔组合,但其语法有特殊要求,例如使用&
而不是和
,并由于&
运算符的优先级,小心地用括号括起条件的各个部分:
>>> results.loc[(results['TeamID'] == 'sw') & (results['todayorno'])]
TeamID todayorno newnew
1 sw True green
.loc
属性还可以按行和列寻址。逗号分隔了寻址部分,其中行的寻址位于第一位,列的寻址位于最后:
>>> results.loc[results['TeamID'] == 'pr', 'todayorno']
1 False
3 True
Name: todayorno, dtype: bool
最后的接触
而.loc
属性也可以用于赋值,方法是将所需的值赋给所需的“坐标”
因此,在你的情况下:
>>> results.loc[
... (results['TeamID'] == 'sw') & (results['todayorno']),
... 'newnew'
... ] = "red"
>>> results
TeamID todayorno newnew
0 sw True red
1 pr False green
2 sw False green
3 pr True green
另一种解决方案
dataframes的.apply()
方法允许多次应用单个函数,可以按列或按行。要按行应用,请传递轴=1
参数
如果传递给.apply(…,axis=1)
的函数的结果返回一个值,则该函数的每个应用程序的结果将以数据帧行的相同寻址(通俗地说是相同索引)组合成一系列
因此:
然后可以将其指定为数据帧的一列:
>>> results['newnew'] = results.apply(
... lambda s: 'red' if s['TeamID'] == 'sw' and s['todayorno'] else 'green',
... axis=1,
... )
>>> results
TeamID todayorno newnew
0 sw True red
1 pr False green
2 sw False green
3 pr True green
您给出了一个示例,说明了在代码运行之前数据帧的外观。你能举一个例子说明你希望dataframe如何处理你的代码运行吗?注意pd.Series.apply
+lambda
应该作为最后的手段使用,因为矢量化解决方案是不可能的。使用布尔级数进行索引比使用行三元语句更有效。谢谢jpp!这完全符合预期。我要读《努比》了你能解释一下这条线是怎么工作的吗?条件=[~mask,mask&results['todayorno'],mask&~results['todayorno']]——让我试一试:您是否选择了所有掩码的反转、使用todayorno的掩码和使用todayorno的反转选择的掩码?然后指定与绿色、红色、绿色相同的顺序?~
表示否定,&
表示“和”或“交叉点”。条件的每一项都与值中的一项匹配。例如,~mask
与'green'
(每个列表中的第一个元素)匹配。
>>> results.apply(
... lambda s: 'red' if s['TeamID'] == 'sw' and s['todayorno'] else 'green',
... axis=1,
... )
0 red
1 green
2 green
3 green
dtype: object
>>> results['newnew'] = results.apply(
... lambda s: 'red' if s['TeamID'] == 'sw' and s['todayorno'] else 'green',
... axis=1,
... )
>>> results
TeamID todayorno newnew
0 sw True red
1 pr False green
2 sw False green
3 pr True green