比较组内的行,熊猫

时间:2021-01-27 02:16:52

标签: python pandas dataframe conditional-statements

我需要的东西看起来很基本,但我正在为此苦苦挣扎,所以我很感激你的帮助。

此代码:

data = pd.DataFrame({'id' : ['a100', 'a100', 'a100', 'a200', 'a200', 'a200','a300','a300', 'a300', 'a400', 'a400', 'a400', 'a500', 'a500', 'a500', 'a600', 'a600', 'a600', 'a700', 'a700', 'a700', 'a800', 'a800', 'a800', 'a900', 'a900', 'a900'],
                    'type': ['euro', 'dollar', 'yen', 'euro', 'dollar', 'yen','euro', 'dollar', 'yen', 'euro', 'dollar', 'yen', 'euro', 'dollar', 'yen', 'euro', 'dollar', 'yen', 'euro', 'dollar', 'yen', 'euro', 'dollar', 'yen', 'euro', 'dollar', 'yen'],
                   'model': ['EQ', 'EQ', 'EQ', 'MC', 'MC', 'MC', 'EQ','EQ', 'EQ', 'MC', 'MC', 'MC', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ'],
                    'status_ant': ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'C', 'A', 'B', 'C', 'A', 'A', 'A', 'A', 'B', 'C', 'B', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'],
                    'status': ['B', 'C', 'A', 'B', 'C', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'C', 'B', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'A', 'B', 'A', 'C', 'C']
                    })

导致此 df:

      id    type model status_ant status
0   a100    euro    EQ          A      B
1   a100  dollar    EQ          A      C
2   a100     yen    EQ          A      A
3   a200    euro    MC          A      B
4   a200  dollar    MC          A      C
5   a200     yen    MC          A      A
6   a300    euro    EQ          B      A
7   a300  dollar    EQ          C      A
8   a300     yen    EQ          A      A
9   a400    euro    MC          B      A
10  a400  dollar    MC          C      A
11  a400     yen    MC          A      A
12  a500    euro    EQ          A      B
13  a500  dollar    EQ          A      C
14  a500     yen    EQ          A      B
15  a600    euro    EQ          B      A
16  a600  dollar    EQ          C      A
17  a600     yen    EQ          B      A
18  a700    euro    EQ          A      A
19  a700  dollar    EQ          A      A
20  a700     yen    EQ          A      B
21  a800    euro    EQ          A      B
22  a800  dollar    EQ          A      A
23  a800     yen    EQ          A      B
24  a900    euro    EQ          A      A
25  a900  dollar    EQ          A      C
26  a900     yen    EQ          A      C

我需要使用某些条件过滤我想要的行。我需要的逻辑是这个:

  • 首先,我要提到的这些条件只适用于模型 == 'EQ' 的行。

  • 如果有一行:

status_ant == 'A' and status == 'B' and type == 'euro'

并且在同一组中还有另一行(按 ID)

status_ant == 'A' and status == 'C' and type == 'dollar'

删除这两行(否则,保留它们)。相同的逻辑适用于行:

status_ant == 'B' and status == 'A' and type == 'euro'

并且在同一组中还有另一行(按 ID)

status_ant == 'C' and status == 'A' and type == 'dollar'

无论 status_ant 和 status 中的值是什么,都不应删除 type == 'yen' 的行。

注意:我知道这可能会令人困惑,但我想要的结果数据帧就是这个(它很好地体现了我提到的所有条件):

      id    type model status_ant status
2   a100     yen    EQ          A      A
3   a200    euro    MC          A      B
4   a200  dollar    MC          A      C
5   a200     yen    MC          A      A
8   a300     yen    EQ          A      A
9   a400    euro    MC          B      A
10  a400  dollar    MC          C      A
11  a400     yen    MC          A      A
14  a500     yen    EQ          A      B
17  a600     yen    EQ          B      A
18  a700    euro    EQ          A      A
19  a700  dollar    EQ          A      A
20  a700     yen    EQ          A      B
21  a800    euro    EQ          A      B
22  a800  dollar    EQ          A      A
23  a800     yen    EQ          A      B
24  a900    euro    EQ          A      A
25  a900  dollar    EQ          A      C
26  a900     yen    EQ          A      C

我正在寻找答案并在这里找到了类似的东西:Pandas: Comparing rows within groups
但无法使其适用于我的代码。

非常感谢您的帮助和时间。 谢谢

2 个答案:

答案 0 :(得分:1)

针对更新的数据运行:

代码还是一样的:

print (df[~(df.model.eq('EQ') & df.status_ant.ne(df.status))])

输入数据:

data = pd.DataFrame({'id' : ['a100', 'a100', 'a100', 'a200', 'a200', 'a200','a300','a300', 'a300', 'a400', 'a400', 'a400'],
                    'model' : ['EQ', 'EQ', 'EQ', 'MC', 'MC', 'MC', 'EQ','EQ', 'EQ', 'MC', 'MC', 'MC', ],
                     'status_ant' : ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'C', 'A', 'B', 'C', 'A'],
                     'status': ['B', 'C', 'A', 'B', 'C', 'A', 'A', 'A', 'A', 'A', 'A', 'A']
                     })

这被加载到数据帧中:

      id model status_ant status
0   a100    EQ          A      B  #exclude this row
1   a100    EQ          A      C  #exclude this row
2   a100    EQ          A      A
3   a200    MC          A      B
4   a200    MC          A      C
5   a200    MC          A      A
6   a300    EQ          B      A #exclude this row
7   a300    EQ          C      A #exclude this row
8   a300    EQ          A      A
9   a400    MC          B      A
10  a400    MC          C      A
11  a400    MC          A      A

更新的数据帧:

      id model status_ant status
2   a100    EQ          A      A
3   a200    MC          A      B
4   a200    MC          A      C
5   a200    MC          A      A
8   a300    EQ          A      A
9   a400    MC          B      A
10  a400    MC          C      A
11  a400    MC          A      A

较早的回答

你在找这个吗:

print (df[~(df.model.eq('EQ') & df.status_ant.ne(df.status))])

请注意,您不需要进行分组。您无法进行分组,因为您实际上是在尝试获取数据的子集。

首先它会检查是否df['model'] == 'EQ'。如果为 true,则它会检查是否 df['status_ant'] != df['status']

通过给出 df['status_ant'] != df['status'],您正在检查所有条件。

status_ant == 'A' and status == 'B', AND status_ant == 'A' and status == 'C'

status_ant == 'B' and status == 'A', AND status_ant == 'C' and status == 'A'

输出结果为:

      id model status_ant status
2   a100    EQ          A      A
3   a200    MC          A      B
4   a200    MC          A      C
5   a200    MC          A      A
8   a300    EQ          A      A
9   a400    MC          B      A
10  a400    MC          C      A
11  a400    MC          A      A

注意:如果您在 status_antstatus 中有其他值,这将不起作用。例如,如果 status_antA 并且 statusDE 并且您希望包含该记录,那么我需要添加一个附加条件.

如果您只想限制对 ABC 的检查,那么您可以给出:

print (df[~(df.model.eq('EQ') & df.status_ant.isin(['A','B','C']) & df.status.isin(['A','B','C']) & df.status_ant.ne(df.status))])

输出结果为:

我用来创建输入数据帧的源代码:

data = pd.DataFrame({'id' : ['a100', 'a100', 'a100', 'a100','a200', 'a200', 'a200','a300','a300', 'a300', 'a400', 'a400', 'a400'],
                    'model' : ['EQ', 'EQ', 'EQ', 'EQ','MC', 'MC', 'MC', 'EQ','EQ', 'EQ', 'MC', 'MC', 'MC', ],
                     'status_ant' : ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'C', 'A', 'B', 'C', 'A'],
                     'status': ['B', 'C', 'A', 'D', 'B', 'C', 'A', 'A', 'A', 'A', 'A', 'A', 'A']
                     })
df = pd.DataFrame(data)

输入数据帧:

      id model status_ant status
0   a100    EQ          A      B  #exclude this row
1   a100    EQ          A      C  #exclude this row
2   a100    EQ          A      A    #include this row
3   a100    EQ          A      D    #include this row
4   a200    MC          A      B
5   a200    MC          A      C
6   a200    MC          A      A
7   a300    EQ          B      A  #exclude this row
8   a300    EQ          C      A  #exclude this row
9   a300    EQ          A      A    #include this row
10  a400    MC          B      A
11  a400    MC          C      A
12  a400    MC          A      A

输出数据帧:

      id model status_ant status
2   a100    EQ          A      A   #included
3   a100    EQ          A      D   #included
4   a200    MC          A      B
5   a200    MC          A      C
6   a200    MC          A      A
9   a300    EQ          A      A   #included
10  a400    MC          B      A
11  a400    MC          C      A
12  a400    MC          A      A

参见索引 3。它有 status = 'D' 并包含在您的结果集中。

答案 1 :(得分:1)

如果对于每个 idtype 的唯一值是可能的测试,如果每组 True 的总和为 2,您可以使用此解决方案:

m0 = data['model']=='EQ' 
m1 = (data['status_ant'] == 'A') & (data['status'] == 'B') & (data['type'] == 'euro')
m2 = (data['status_ant'] == 'A') & (data['status'] == 'C') & (data['type'] == 'dollar')

m3 = (data['status_ant'] == 'B') & (data['status'] == 'A') & (data['type'] == 'euro')
m4 = (data['status_ant'] == 'C') & (data['status'] == 'A') & (data['type'] == 'dollar')

mask = m0 & (m1 | m2 | m3 | m4)

mask_groups = mask.groupby(data['id']).transform('sum').eq(2)

data = data[~mask | ~mask_groups]
print (data)
      id    type model status_ant status
2   a100     yen    EQ          A      A
3   a200    euro    MC          A      B
4   a200  dollar    MC          A      C
5   a200     yen    MC          A      A
8   a300     yen    EQ          A      A
9   a400    euro    MC          B      A
10  a400  dollar    MC          C      A
11  a400     yen    MC          A      A
14  a500     yen    EQ          A      B
17  a600     yen    EQ          B      A
18  a700    euro    EQ          A      A
19  a700  dollar    EQ          A      A
20  a700     yen    EQ          A      B
21  a800    euro    EQ          A      B
22  a800  dollar    EQ          A      A
23  a800     yen    EQ          A      B
24  a900    euro    EQ          A      A
25  a900  dollar    EQ          A      C
26  a900     yen    EQ          A      C

如果可能的值不是唯一的,则可以通过 any 进行测试,如果每个组匹配,则更改 a100 的数据:

data = pd.DataFrame({'id' : ['a100', 'a100', 'a100', 'a200', 'a200', 'a200','a300','a300', 'a300', 'a400', 'a400', 'a400', 'a500', 'a500', 'a500', 'a600', 'a600', 'a600', 'a700', 'a700', 'a700', 'a800', 'a800', 'a800', 'a900', 'a900', 'a900'],
                    'type': ['euro', 'dollar', 'dollar', 'euro', 'dollar', 'yen','euro', 'dollar', 'yen', 'euro', 'dollar', 'yen', 'euro', 'dollar', 'yen', 'euro', 'dollar', 'yen', 'euro', 'dollar', 'yen', 'euro', 'dollar', 'yen', 'euro', 'dollar', 'yen'],
                   'model': ['EQ', 'EQ', 'EQ', 'MC', 'MC', 'MC', 'EQ','EQ', 'EQ', 'MC', 'MC', 'MC', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ', 'EQ'],
                    'status_ant': ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'C', 'A', 'B', 'C', 'A', 'A', 'A', 'A', 'B', 'C', 'B', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'],
                    'status': ['B', 'C', 'C', 'B', 'C', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'C', 'B', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'A', 'B', 'A', 'C', 'C']
                    })

m0 = data['model']=='EQ' 
m1 = (data['status_ant'] == 'A') & (data['status'] == 'B') & (data['type'] == 'euro')
m2 = (data['status_ant'] == 'A') & (data['status'] == 'C') & (data['type'] == 'dollar')

m3 = (data['status_ant'] == 'B') & (data['status'] == 'A') & (data['type'] == 'euro')
m4 = (data['status_ant'] == 'C') & (data['status'] == 'A') & (data['type'] == 'dollar')

mask1 = m0 & (m1 | m3)
mask2 = m0 & (m2 | m4)

mask_euro = mask1.groupby(data['id']).transform(any)
mask_dolar = mask2.groupby(data['id']).transform(any)

data = data[~(mask1 | mask2) | ~(mask_euro & mask_dolar)]

print (data)
     id    type model status_ant status
3   a200    euro    MC          A      B
4   a200  dollar    MC          A      C
5   a200     yen    MC          A      A
8   a300     yen    EQ          A      A
9   a400    euro    MC          B      A
10  a400  dollar    MC          C      A
11  a400     yen    MC          A      A
14  a500     yen    EQ          A      B
17  a600     yen    EQ          B      A
18  a700    euro    EQ          A      A
19  a700  dollar    EQ          A      A
20  a700     yen    EQ          A      B
21  a800    euro    EQ          A      B
22  a800  dollar    EQ          A      A
23  a800     yen    EQ          A      B
24  a900    euro    EQ          A      A
25  a900  dollar    EQ          A      C
26  a900     yen    EQ          A      C