首页 > 解决方案 > Pandas 按循环状态分组

问题描述

我有一个数据集,其中的主机按时间排序,如果是正确的,则有一个状态。我只想获得至少连续 3 次被评为“假”的主机。也就是说,如果计数器之间有一个 True 应该重置。

data = {'time': ['10:01', '10:02', '10:03', '10:15', '10:16', '10:18','10:20','10:21','10:22', '10:23','10:24','10:25','10:26','10:27'],
        'host': ['A','B','A','A','A','B','A','A','B','B','B','B','B','B'],
        'isCorrect': [True, True, False, True, False, False, True, True, False, False, True, False, False, False]}

     time host  isCorrect
0   10:01    A       True
1   10:02    B       True
2   10:03    A      False
3   10:15    A       True
4   10:16    A      False
5   10:18    B      False
6   10:20    A       True
7   10:21    A       True
8   10:22    B      False
9   10:23    B      False
10  10:24    B       True
11  10:25    B      False
12  10:26    B      False
13  10:27    B      False

对于这个示例数据集,应该有 2 个集群:

  1. 主机 B 由于第 5、8、9 行,因为它们连续 3 次为 False。
  2. 主机 B 由于第 11、12、13 行

请注意,它应该是 2 个集群,而不是 1 个由 6 个项目组成的集群。不幸的是,我的实现正是这样做的。

df = pd.DataFrame(data)
df = df[~df['isCorrect']].sort_values(['host','time'])

mask = df['host'].map(df['host'].value_counts()) >= 3

df = df[mask].copy()
df['Group'] = pd.factorize(df['host'])[0]

哪个返回

     time host  isCorrect  Group
5   10:18    B      False      0
8   10:22    B      False      0
9   10:23    B      False      0
11  10:25    B      False      0
12  10:26    B      False      0
13  10:27    B      False      0

预期是这样的输出:

     time host  isCorrect  Group
5   10:18    B      False      0
8   10:22    B      False      0
9   10:23    B      False      0
11  10:25    B      False      1
12  10:26    B      False      1
13  10:27    B      False      1

标签: pythonpandasdataframe

解决方案


Group使用 s 的累积总和排序后生成新列的解决方案已更改True(因为已测试Falses),因此生成了在最后一步中分解的唯一组:

df = df.sort_values(['host','time'])

df['Group'] = df['isCorrect'].cumsum()
df = df[~df['isCorrect']]

mask = df['Group'].map(df['Group'].value_counts()) >= 3

df = df[mask].copy()
df['Group'] = pd.factorize(df['Group'])[0]
print (df)
     time host  isCorrect  Group
5   10:18    B      False      0
8   10:22    B      False      0
9   10:23    B      False      0
11  10:25    B      False      1
12  10:26    B      False      1
13  10:27    B      False      1

df = df.sort_values(['host','time'])

df['Group'] = df['isCorrect'].cumsum()
df = df[~df['isCorrect']]

mask = df['Group'].map(df['Group'].value_counts()) >= 5

df = df[mask].copy()
df['Group'] = pd.factorize(df['Group'])[0]
print (df)
Empty DataFrame
Columns: [time, host, isCorrect, Group]
Index: []

推荐阅读