python - Pandas 匹配多列模式

标签 python pandas

我有一个由 bool 值组成的数据框。我想匹配数据框中的某些多列模式。该模式看起来像:

    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 值,以及缺乏通配符支持(为了支持不一定是盒形模式)。

有什么建议吗?

最佳答案

如果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

关于python - Pandas 匹配多列模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44818663/

相关文章:

python - 如何将 Dataframe 时间增加 5 分钟间隔?

python - 根据条件计算出现次数并保存在新列中

python - 为 "singleton"非模型对象创建一个 tastypie 资源

python - Python中的单元测试用于具有多个返回值的方法

生成器长度至少为 n 的 Pythonic 方式

python - 在 GUI 记录器中添加颜色

python - 如何读取 2 列 csv 文件并创建字典?

python - pandas批量API请求

python - Pandas 日期时间列的矢量化操作

python - 类似于 "Generate n-grams from Pandas column while persisting another column"(未解决),但有值