如何通过将条件应用于值为元组的列来过滤数据框?
How do I filter a dataframe by applying a condition to a column whose values are tuples?
我有一个数据框,其列值是元组。如果不重新创建数据框,是否有一种处理数据框的方法,以便按照以下示例过滤数据框:
构造数据框(请原谅复杂的构造):
import pandas as pd
columns = ['Fruit','Color','Firmness','Volume']
data = [['Apple','Green','Soft',5],
['Apple','Red','Firm',5],
['Blueberry','Blue','Soft',5],
['Blueberry','Blue','Soft',5],
['Pear','Green','Soft',5],
['Pear','Green','Firm',5]]
df = pd.DataFrame(data=data,columns=columns,index=[0,1,2,3,4,5])
def all_values(values):
return tuple([value for value in values])
agg_dict = {'Color':all_values,'Firmness':all_values,'Volume':'sum'}
df = df.groupby(by='Fruit').agg(agg_dict)
df
Color Firmness Volume
Fruit
Apple (Green, Red) (Soft, Firm) 10
Blueberry (Blue, Blue) (Soft, Soft) 10
Pear (Green, Green) (Soft, Firm) 10
现在,我想要实现的是 return 一个仅显示元组中第二个值为 'Firm' 的行的数据框。在这种情况下,这将是 Apple 行和 Pear 行。
是否有类似于 .str.contains 方法的方法可供我在此实例中使用?为了相应地过滤数据框?或者任何其他可以直接执行过滤的合适方法?
谢谢!
更新:
这是一个至少显示了预期结果的尝试,但没有达到目标,因为我必须将 'Soft' 指定为元组的第一部分,而这不是必需的。它也感觉很像黑客:
df = df.where(df['Firmness'] == ('Soft', 'Firm')).dropna()
df
Color Firmness Volume
Fruit
Apple (Green, Red) (Soft, Firm) 10.0
Pear (Green, Green) (Soft, Firm) 10.0
尝试使用 agg
和 if...else
out = df.groupby('Fruit').agg(lambda x : x.sum() if x.dtype==int else tuple(x))
Out[332]:
Color Firmness Volume
Fruit
Apple (Green, Red) (Soft, Firm) 10
Blueberry (Blue, Blue) (Soft, Soft) 10
Pear (Green, Green) (Soft, Firm) 10
那么对于你的问题
out = out[out.Firmness.str[1]=='Firm']
out
Out[335]:
Color Firmness Volume
Fruit
Apple (Green, Red) (Soft, Firm) 10
Pear (Green, Green) (Soft, Firm) 10
对于你的问题,使用 apply 和 lambda
df[df.apply(lambda x:x.Firmness[1]=='Firm' , axis=1)]
我有一个数据框,其列值是元组。如果不重新创建数据框,是否有一种处理数据框的方法,以便按照以下示例过滤数据框:
构造数据框(请原谅复杂的构造):
import pandas as pd
columns = ['Fruit','Color','Firmness','Volume']
data = [['Apple','Green','Soft',5],
['Apple','Red','Firm',5],
['Blueberry','Blue','Soft',5],
['Blueberry','Blue','Soft',5],
['Pear','Green','Soft',5],
['Pear','Green','Firm',5]]
df = pd.DataFrame(data=data,columns=columns,index=[0,1,2,3,4,5])
def all_values(values):
return tuple([value for value in values])
agg_dict = {'Color':all_values,'Firmness':all_values,'Volume':'sum'}
df = df.groupby(by='Fruit').agg(agg_dict)
df
Color Firmness Volume
Fruit
Apple (Green, Red) (Soft, Firm) 10
Blueberry (Blue, Blue) (Soft, Soft) 10
Pear (Green, Green) (Soft, Firm) 10
现在,我想要实现的是 return 一个仅显示元组中第二个值为 'Firm' 的行的数据框。在这种情况下,这将是 Apple 行和 Pear 行。
是否有类似于 .str.contains 方法的方法可供我在此实例中使用?为了相应地过滤数据框?或者任何其他可以直接执行过滤的合适方法?
谢谢!
更新:
这是一个至少显示了预期结果的尝试,但没有达到目标,因为我必须将 'Soft' 指定为元组的第一部分,而这不是必需的。它也感觉很像黑客:
df = df.where(df['Firmness'] == ('Soft', 'Firm')).dropna()
df
Color Firmness Volume
Fruit
Apple (Green, Red) (Soft, Firm) 10.0
Pear (Green, Green) (Soft, Firm) 10.0
尝试使用 agg
和 if...else
out = df.groupby('Fruit').agg(lambda x : x.sum() if x.dtype==int else tuple(x))
Out[332]:
Color Firmness Volume
Fruit
Apple (Green, Red) (Soft, Firm) 10
Blueberry (Blue, Blue) (Soft, Soft) 10
Pear (Green, Green) (Soft, Firm) 10
那么对于你的问题
out = out[out.Firmness.str[1]=='Firm']
out
Out[335]:
Color Firmness Volume
Fruit
Apple (Green, Red) (Soft, Firm) 10
Pear (Green, Green) (Soft, Firm) 10
对于你的问题,使用 apply 和 lambda
df[df.apply(lambda x:x.Firmness[1]=='Firm' , axis=1)]