首页 > 解决方案 > 数据帧计数每行由几列传递的条件集

问题描述

我有一个看起来像这样的数据框:

date   A_1  A_2  A_3  B_1  B_2  B_3  C_1  C_2  C_3  D_1  D_2  D_3
xxx    4    5    6    2    3    1    5    7    2    4    3    1
xxx    3    3    2    4    5    2    6    2    3    2    4    2
xxx    5    7    5    1    3    3    4    5    4    8    2    2
xxx    6    1    8    6    1    4    1    2    7    4    3    5

我正在尝试根据每行的条件计算一个值,该条件将应用于 A、B、C、D 等的列分组,并计算这些组中有多少通过了条件,例如,一些伪代码:

count = 0
for each (A, B, C, D) as col:
    if col_1 > 3 and (col_2 > col_3):
        count++

dataframe['count'] = count   

预期输出:

date   A_1  A_2  A_3  B_1  B_2  B_3  C_1  C_2  C_3  D_1  D_2  D_3  count
xxx    4    5    6    2    3    1    5    7    2    4    3    1    2
xxx    3    3    2    4    5    2    6    2    3    2    4    2    1
xxx    5    7    5    1    3    3    4    5    4    8    2    2    2
xxx    6    1    8    6    1    4    1    2    7    4    3    5    0

这意味着示例数据框将以值为 2 的新列结束,因为在此示例中,列 C 和 D 传递了一组条件。

稍后我计划为每一行做一些事情,计数值高于某个数字。

我能想出的最好方法是这样的:

for col in cols:
    conditions.append(
        (
            (dataframe[f'{col}_1'] > min_corr_coef) & 
            (dataframe[f'{col}_2'] < (dataframe[f'{col_3}])
        ) | 
        (dataframe[f'{col}_1'] <= min_corr_coef)
    )

conditions.append(
    (dataframe[dataframe.loc[:,cols] > min_corr_coef].count(axis=1) >= min_corr_pair)
)

if conditions:
    dataframe.loc[
        reduce(lambda x, y: x & y, conditions),
        'pass'] = 1

这不仅不正确,而且速度极慢。我喜欢它的是它是可读的,如果有更多的列/不同的数据,添加额外的条件相对简单。

我不确定这种类型的操作是否太复杂而无法按照我尝试的方式在数据帧上执行,也许我需要更改我的数据结构,但我想我会看看是否有一些方法可以解决这在我开始重新写东西之前。

理想情况下,应用于列组(在这种情况下为 A、B、C、D)的逻辑可以是模块化的,并且我用来执行此操作的任何方法都应该易于添加/删除条件,因为我希望能够添加/删除数据列和逻辑条件随时间变化。

我正在尝试做的是在一组列(相关系数)高于某个值时测试一组任意条件。如果有足够多的列组通过条件,请执行一些操作。

在此先感谢,我是 python 和 pandas 新手,这让我头疼了好几天。

标签: pythonpandas

解决方案


单线解决方案:

>>> sum(df1.iloc[:, range(3*i,3*(i+1))].apply(lambda x: x[0] > 3 and (x[1] > x[2]), axis=1) for i in range(len(df1.columns)//3)).tolist()

[2]

方法:使用.iloc[]slicing,如果可以保证列名出现在三个命名的常规组中X_1, X_2, X_3

for i in range(len(df.columns)//3):
    df.iloc[:, range(3*i,3*(i+1))]
  
      A_1  A_2  A_3
date               
xxx     4    5    6
      B_1  B_2  B_3
date               
xxx     2    3    1
      C_1  C_2  C_3
date               
xxx     5    7    2
      D_1  D_2  D_3
date               
xxx     4    3    1

然后你可以apply(..., axis=1)在三列的每一片上使用任何你想要的lamba函数或自定义函数:

for i in range(len(df1.columns)//3):
    # Your commands go here, print()ing just as an example
    print(df1.iloc[:, range(3*i,3*(i+1))])
    print(df1.iloc[:, range(3*i,3*(i+1))].apply(lambda x: x[0] > 3 and (x[1] > x[2]), axis=1))

      A_1  A_2  A_3
date               
xxx     4    5    6
date
xxx    False
dtype: bool
      B_1  B_2  B_3
date               
xxx     2    3    1
date
xxx    False
dtype: bool
      C_1  C_2  C_3
date               
xxx     5    7    2
date
xxx    True
dtype: bool
      D_1  D_2  D_3
date               
xxx     4    3    1
date
xxx    True
dtype: bool

现在您可以apply()跨越每列切片的三列,然后sum()垂直,或任何您想要的(而不是带增量的 for 循环。)


推荐阅读