Python:使用Pandas在csv中打印具有匹配列内容的行名称

时间:2015-02-07 20:47:09

标签: python csv pandas

所以,我在Python中使用pandas。我正在读一个看起来像这样的csv:

imageName     color1     color2     color3     color4
img1          Red        Red        Red        Red
img2          Blue       Green      Red        Blue
img3          Yellow     Blue       Red        White
img4          Blue       Blue       Blue       Blue

如果color1,color2,color3和color4都相等,我想要的是打印行(按图像名称)。 如果我在SQL中这样做

SELECT: imageName 
FROM: rows 
WHERE: color1 == color2 == color3 == color4

会给我img1和img4

我对Pandas很新,并且一直试图弄清楚语法,但我一直遇到问题。

我现在正在尝试的是:

if (df[(df['color1'] == df['color2'] == df['color3'] == df['color4']])]
    print df['imageName']

但无论我尝试什么,我都会遇到错误。

我得到了:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any(), or a.all().

但我正在努力弄清楚在哪里使用它们。或者如果我甚至以正确的方式去做。提前谢谢!

2 个答案:

答案 0 :(得分:2)

这是一种方法,我试图找出一个矢量化方法,基本上你定义了一个函数,它接受你的行然后调用apply,传递函数名和param axis=1以逐行应用。 color_cols只是由color_cols = [col for col in df if 'color' in col]

定义的颜色列名称列表
In [21]:

def all_equal(x):
    return x['color1'] == x['color2'] == x['color3'] == x['color4']

df[color_cols].apply(all_equal, axis=1)
Out[21]:
0     True
1    False
2    False
3     True
dtype: bool
In [23]:

df[df[color_cols].apply(all_equal, axis=1)]['imageName']
Out[23]:
0    img1
3    img4
Name: imageName, dtype: object

更快的方法是定义一个掩码并使用按位运算符:

In [27]:
# mask tests if color 1 equals color 2 and color 3 equals color 4 and color 1 equals color 3 if this is true then all must be the same value
mask = (df['color1'] == df['color2']) & (df['color3'] == df['color4']) & (df1['color1'] == df['color3'])
mask
Out[27]:
0     True
1    False
2    False
3     True
dtype: bool
In [28]:

df[mask]['imageName']
Out[28]:
0    img1
3    img4
Name: imageName, dtype: object

<强>计时

In [29]:

%timeit df.query("color1 == color2 == color3 == color4").imageName
100 loops, best of 3: 7.24 ms per loop
In [30]:

%timeit df[(df['color1'] == df['color2']) & (df['color3'] == df['color4']) & (df1['color1'] == df['color3'])].imageName

100 loops, best of 3: 3.22 ms per loop

另一种方法是调用eval

In [39]:

%timeit df[df.eval("color1 == color2 & color3 == color4 & color1 == color3")].imageName
100 loops, best of 3: 7.53 ms per loop

In [40]:

%timeit df[df[color_cols].apply(all_equal, axis=1)].imageName
100 loops, best of 3: 2.55 ms per loop

掩码方法比此样本数据集的查询和eval方法快2倍。 apply方法实际上是最快的方法,但它不会像其他方法那样扩展,因为它实际上循环遍历每一行。

答案 1 :(得分:2)

您可以使用query:获取类似语法:

>>> df.query("color1 == color2 == color3 == color4")
  imageName color1 color2 color3 color4
0      img1    Red    Red    Red    Red
3      img4   Blue   Blue   Blue   Blue
>>> df.query("color1 == color2 == color3 == color4").imageName
0    img1
3    img4
Name: imageName, dtype: object

或者,您可以使用布尔系列索引:

>>> df[df.filter(like="color").apply(pd.Series.nunique, axis=1) == 1]
  imageName color1 color2 color3 color4
0      img1    Red    Red    Red    Red
3      img4   Blue   Blue   Blue   Blue

虽然这略有不同,因为nunique会忽略NaN