有一个像这样的数据帧:
pd.DataFrame({"type":["type1","type1","type1","type2","type2","type2","type1/type2","type1/type2","type1/type2"],
"id": [1,2,3,1,2,3,1,2,3],
"values":[1,np.nan,7,np.nan,5,np.nan,1,1,1]})
:
类型 | id | 价值观 |
---|---|---|
type1 | 1 | 1 |
type1 | 2 | NaN |
type1 | 3 | 7 |
type2 | 1 | NaN |
type2 | 2 | 5 |
type2 | 3 | NaN |
type1,type2 | 1 | 1 |
type1,type2 | 2 | 1 |
type1,type2 | 3 | 1 |
我有一个这样的“指南”(带有它们对应的 id 的类型):
type1 = [1,3]
type2 = [2,3]
type1,type2 = [1,2,3]
我想根据此列表过滤行(您可以看到有两种可能的情况:type1-id2 = NaN 需要过滤,但 type2-id3=NaN - 是有效值)>
我如何才能以最佳方式执行此操作?事实上,我有更大的桌子和更多的指南列表。
答案 0 :(得分:2)
我建议创建字典,然后使用 np.logical_or.reduce 选择字典中的值循环使用 Series.eq
用于 ==
和 Series.isin
用于检查成员资格,最后传递到 {{3 }}:
d = {}
d['type1'] = [1,3]
d['type2'] = [2,3]
d['type1/type2'] = [1,2,3]
print (d)
{'type1': [1, 3], 'type2': [2, 3], 'type1/type2': [1, 2, 3]}
m = np.logical_or.reduce([df['type'].eq(k) & df['id'].isin(v) for k, v in d.items()])
df = df[m]
print (df)
type id values
0 type1 1 1.0
2 type1 3 7.0
4 type2 2 5.0
5 type2 3 NaN
6 type1/type2 1 1.0
7 type1/type2 2 1.0
8 type1/type2 3 1.0
另一种方法是创建新的 DataFrame 并按原始数据合并所有相交的列,此处为 type
和 id
列:
d = {}
d['type1'] = [1,3]
d['type2'] = [2,3]
d['type1/type2'] = [1,2,3]
print (d)
df1 = pd.DataFrame([(k, x) for k, v in d.items() for x in v], columns=['type','id'])
print (df1)
type id
0 type1 1
1 type1 3
2 type2 2
3 type2 3
4 type1/type2 1
5 type1/type2 2
6 type1/type2 3
df = df.merge(df1)
print (df)
type id values
0 type1 1 1.0
1 type1 3 7.0
2 type2 2 5.0
3 type2 3 NaN
4 type1/type2 1 1.0
5 type1/type2 2 1.0
6 type1/type2 3 1.0
答案 1 :(得分:2)
创建从类型到有效 ID 的映射:
d = {'type1':[1, 3], 'type2':[2, 3], 'type1/type2': [1, 2, 3]}
然后为要保留的 id 创建布尔映射:
keep_bool = [id in d[type] for type, id in zip(df['type'], df['id'])]
然后只保留有效索引。
df = df[keep_bool]
输入:
type id values
0 type1 1 1.0
1 type1 2 NaN
2 type1 3 7.0
3 type2 1 NaN
4 type2 2 5.0
5 type2 3 NaN
6 type1/type2 1 1.0
7 type1/type2 2 1.0
8 type1/type2 3 1.0
输出:
>>> df[keep_bool]
type id values
0 type1 1 1.0
2 type1 3 7.0
4 type2 2 5.0
5 type2 3 NaN
6 type1/type2 1 1.0
7 type1/type2 2 1.0
8 type1/type2 3 1.0
答案 2 :(得分:1)
您可以结合使用 itertools
以及索引来过滤您想要的值:
from itertools import product, chain
d = {'type1':[1, 3], 'type2':[2, 3], 'type1/type2': [1, 2, 3]}
combinations = chain.from_iterable(product([key], value)
for key, value
in d.items()
)
df.set_index(['type', 'id']).loc[combinations].reset_index()
type id values
0 type1 1 1.0
1 type1 3 7.0
2 type2 2 5.0
3 type2 3 NaN
4 type1/type2 1 1.0
5 type1/type2 2 1.0
6 type1/type2 3 1.0