按参数列表过滤数据框

时间:2021-04-06 08:01:44

标签: python pandas

有一个像这样的数据帧:

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 - 是有效值)

我如何才能以最佳方式执行此操作?事实上,我有更大的桌子和更多的指南列表。

3 个答案:

答案 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 并按原始数据合并所有相交的列,此处为 typeid 列:

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