Pandas匹配多列模式

2024-04-25 01:09:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个由布尔值组成的数据帧。我想在数据帧中匹配某些多列模式。模式如下所示:

    bar     foo
0   False   True
1   True    False

预期输出如下所示:

      foo    bar pattern
0    True  False   False
1    True  False   False
2    True  False    True
3   False   True   False
4   False   True   False
5   False   True   False
6   False  False   False
7   False  False   False
8   False  False   False
9   False   True   False
10  False   True   False
11  False   True   False
12  False   True   False
13  False   True   False
14  False   True   False
15  False   True   False
16   True  False   False
17   True  False   False
18   True  False    True
19  False   True   False
20  False   True   False
21  False   True   False
22   True  False    True
23  False   True   False
24  False   True   False
25  False   True   False

我提出了我自己的实现,但我想应该有一个更好的。你知道吗

def matcher(df, pattern):
    def aggregator(pattern):
        """Returns a dict of columnswith their aggregator function
        which is the partially applied inner in this case"""
        def inner(col, window):
            return (window == pattern[col]).all()
        return {col: partial(inner, col) for col in pattern.columns}

    aggregated = (df
                  # Feed the chunks to aggregator in `len(pattern)` sized windows
                  .rolling(len(pattern))
                  .aggregate(aggregator(pattern))
                  # I'd like it to return True at the beginning of the match
                  .shift(-len(pattern) + 1)
                  # rows consisting of nan return true to `.all()`
                  .fillna(False))
    ret = [row.all() for _, row in aggregated.iterrows()]
    return pd.Series(ret)

我最担心的是处理nan值,以及缺少通配符支持(为了支持不一定是长方体模式)。你知道吗

有什么建议吗?你知道吗


Tags: ofthetoinfalsetruelenreturn
2条回答

如果pd.concat()对您来说不是太贵,那么下面的代码将非常高效地工作,因为没有循环和嵌套函数。你知道吗

print(df)  # Original data without 'pattern' column.

df_wide = pd.concat([df, df.shift(-1)], axis=1)
df_wide.columns = ['foo0', 'bar0', 'foo-1', 'bar-1']

pat = ((df_wide['foo0'] == True) & (df_wide['bar-1'] == True)) & \
      ((df_wide['bar0'] == False) & (df_wide['foo-1'] == False)) 

df['pattern'] = False
df.loc[df_wide[pat].index, 'pattern'] = True

print(df)  # Result data with 'pattern' column.

# Original data without 'pattern' column.
      foo    bar
0    True  False
1    True  False
2    True  False
3   False   True
4   False   True
5   False   True
...

# Result data with 'pattern' column.
      foo    bar  pattern
0    True  False    False
1    True  False    False
2    True  False     True
3   False   True    False
4   False   True    False
5   False   True    False
6   False  False    False
7   False  False    False
8   False  False    False
9   False   True    False
10  False   True    False
11  False   True    False
12  False   True    False
13  False   True    False
14  False   True    False
15  False   True    False
16   True  False    False
17   True  False    False
18   True  False     True
19  False   True    False
20  False   True    False
21  False   True    False
22   True  False     True
23  False   True    False
24  False   True    False
25  False   True    False

假设df1是您的模式df,df2是您的值df,您可以使用apply检查模式。对于每一行,我们得到当前行和下一行,然后将2*2数组与df1元素else进行比较,检查所有元素是否相同。你知道吗

df2.apply(lambda x: (df2[['foo','bar']].iloc[x.name:x.name+2].values\
                     ==df1[['foo','bar']].values).all(),axis=1)
Out[213]: 
0     False
1     False
2      True
3     False
4     False
5     False
6     False
7     False
8     False
9     False
10    False
11    False
12    False
13    False
14    False
15    False
16    False
17    False
18     True
19    False
20    False
21    False
22     True
23    False
24    False
25    False
dtype: bool

相关问题 更多 >