python - 通过元组列表过滤 DataFrame 的行
问题描述
假设我有以下 DataFrame:
dic = {'a' : [1, 1, 2, 2, 2, 2, 3, 3, 3, 3],
'b' : [1, 1, 1, 1, 2, 2, 1, 1, 2, 2],
'c' : ['f', 'f', 'f', 'e', 'f', 'f', 'f', 'e', 'f', 'f'],
'd' : [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]}
df = pd.DataFrame(dic)
df
Out[10]:
a b c d
0 1 1 f 10
1 1 1 f 20
2 2 1 f 30
3 2 1 e 40
4 2 2 f 50
5 2 2 f 60
6 3 1 f 70
7 3 1 e 80
8 3 2 f 90
9 3 2 f 100
在下面,我想获取 a 和 b 列的值,其中 c='e' 并使用这些值来选择 df 的相应行(这将过滤第 2、3、6、7 行)。这个想法是创建一个元组列表并按该列表索引 df :
list_tup = list(df.loc[df['c'] == 'e', ['a','b']].to_records(index=False))
df_new = df.set_index(['a', 'b']).sort_index()
df_new
Out[13]:
c d
a b
1 1 f 10
1 f 20
2 1 f 30
1 e 40
2 f 50
2 f 60
3 1 f 70
1 e 80
2 f 90
2 f 100
list_tup
Out[14]: [(2, 1), (3, 1)]
df.loc[list_tup]
导致 TypeError: unhashable type: 'writeable void-scalar',我不明白。有什么建议么?我对 python 和 pandas 很陌生,因此我认为我错过了一些基本的东西。
解决方案
我相信groupby().transform()
在这个用例中使用布尔索引会更好:
valids = (df['c'].eq('e') # check if `c` is 'e`
.groupby([df['a'],df['b']]) # group by `a` and `b`
.transform('any') # check if `True` occurs in the group
# use the same label for all rows in group
)
# filter with `boolean indexing
df[valids]
输出:
a b c d
2 2 1 f 30
3 2 1 e 40
6 3 1 f 70
7 3 1 e 80
一个类似的想法,groupby().filter()
它更具可读性但可能会稍微慢一些:
df.groupby(['a','b']).filter(lambda x: x['c'].eq('e').any())
推荐阅读
- python - 如何在不使用 df.iterrows() 的情况下将 Pandas DataFrame 的列转换为最内层索引?
- javascript - 如何获取用户输入以获取 api url?
- asynchronous - Sync trait 是 Send trait 的严格子集吗?什么实现了没有发送的同步?
- java - 方法 Max(__,__) 未定义类型 (Java)
- amazon-web-services - 无法提取机密或注册表身份验证:拉命令失败::信号:已杀死
- oracle - 带有 CASE 的 Oracle listagg
- r - ggplot中多个系列图例的问题
- r - 如何得到5的倍数之和
- node.js - 为什么当mongoose的console.log(object.property)时我得到未定义
- forms - 根据需要标记文件/路径文件夹以便在表单设计器中继续?