pandas - Pandas 遍历行和条件计数
问题描述
我正在尝试在一个名为 Stage 的新列中使用条件计数迭代 pandas Dataframe 中的行。对于每个名称,阶段应该从 1 开始,如果行之间的名称相同,那么在“健康”状态之后应该开始一个新阶段。如果存在,“健康”事件将与之前的“生病”事件处于同一阶段。我以前在excel中完成过代码,但不知道如何在python中完成。
我现在拥有的是:
日期 | 姓名 | 地位 |
---|---|---|
2020-01-02 | 玛丽 | 健康 |
2020-01-05 | 玛丽 | 生病的 |
2020-01-15 | 玛丽 | 生病的 |
2020-01-20 | 玛丽 | 健康 |
2020-02-03 | 玛丽 | 健康 |
2020-02-06 | 玛丽 | 生病的 |
2020-02-10 | 玛丽 | 生病的 |
2020-02-15 | 玛丽 | 健康 |
2020-01-02 | 鲍勃 | 健康 |
2020-01-05 | 鲍勃 | 健康 |
2020-01-15 | 鲍勃 | 健康 |
2020-01-20 | 鲍勃 | 生病的 |
2020-02-03 | 鲍勃 | 生病的 |
2020-02-06 | 鲍勃 | 生病的 |
2020-02-10 | 鲍勃 | 生病的 |
2020-02-15 | 鲍勃 | 健康 |
我想拥有的:
日期 | 姓名 | 地位 | 阶段 |
---|---|---|---|
2020-01-02 | 玛丽 | 健康 | 1 |
2020-01-05 | 玛丽 | 生病的 | 2 |
2020-01-15 | 玛丽 | 生病的 | 2 |
2020-01-20 | 玛丽 | 健康 | 2 |
2020-02-03 | 玛丽 | 健康 | 3 |
2020-02-06 | 玛丽 | 生病的 | 4 |
2020-02-10 | 玛丽 | 生病的 | 4 |
2020-02-15 | 玛丽 | 健康 | 4 |
2020-01-02 | 鲍勃 | 健康 | 1 |
2020-01-05 | 鲍勃 | 健康 | 2 |
2020-01-15 | 鲍勃 | 健康 | 3 |
2020-01-20 | 鲍勃 | 生病的 | 4 |
2020-02-03 | 鲍勃 | 生病的 | 4 |
2020-02-06 | 鲍勃 | 生病的 | 4 |
2020-02-10 | 鲍勃 | 生病的 | 4 |
2020-02-15 | 鲍勃 | 健康 | 4 |
解决方案
您不需要显式循环。您需要以下内容:
- 按名称列分组
- 适用于每个组:
- 移动状态列以查看上一个值
- 取以下系列的累积总和:
- 如果前一个值为空且当前值为健康,我们在第一行所以称它为一个
- 如果上一行是健康的,就叫它一个
- 否则,称其为零
from io import StringIO
import numpy
import pandas
df = pandas.read_csv(StringIO("""\
|Date|Name|Stage|
|2020-01-02|Mary|Healthy|
|2020-01-05|Mary|Sick|
|2020-01-15|Mary|Sick|
|2020-01-20|Mary|Healthy|
|2020-02-03|Mary|Healthy|
|2020-02-06|Mary|Sick|
|2020-02-10|Mary|Sick |
|2020-02-15|Mary|Healthy|
|2020-01-02|Bob|Healthy|
|2020-01-05|Bob|Healthy|
|2020-01-15|Bob|Healthy|
|2020-01-20|Bob|Sick|
|2020-02-03|Bob|Sick|
|2020-02-06|Bob|Sick|
|2020-02-10|Bob|Sick |
|2020-02-15|Bob|Healthy|
"""), sep='|').loc[:, ['Date', 'Name', 'Stage']]
output = (
df.assign(Status=lambda df: df.groupby('Name')['Stage'].apply(lambda g:
numpy.bitwise_or( # returns 1 if either two conditions are met
g.shift().eq('Healthy'), # general case
g.shift().isnull() & g.eq("Healthy") # handles first row of a group
).cumsum()
))
)
print(output.to_string())
我得到:
Date Name Stage Status
0 2020-01-02 Mary Healthy 1
1 2020-01-05 Mary Sick 2
2 2020-01-15 Mary Sick 2
3 2020-01-20 Mary Healthy 2
4 2020-02-03 Mary Healthy 3
5 2020-02-06 Mary Sick 4
6 2020-02-10 Mary Sick 4
7 2020-02-15 Mary Healthy 4
8 2020-01-02 Bob Healthy 1
9 2020-01-05 Bob Healthy 2
10 2020-01-15 Bob Healthy 3
11 2020-01-20 Bob Sick 4
12 2020-02-03 Bob Sick 4
13 2020-02-06 Bob Sick 4
14 2020-02-10 Bob Sick 4
15 2020-02-15 Bob Healthy 4
推荐阅读
- javascript - 在javascript中为粒子添加不透明度?
- javascript - JS 中的函数没有显示任何输出。我也看不到任何错误
- javascript - sleep() await 仅在异步函数中有效
- reactjs - 为什么不直接从 action creator redux 发送到 store?
- android - Dagger2:无法在 WorkManager 中注入依赖项
- php - 模块 pcntl 已在第 0 行的未知中加载 - Apache x Cli
- javascript - 如何在 Webpack 中使用多个条目以及 HtmlWebpackPlugin 中的多个 HTML 文件?
- javascript - JavaScript function(callback).then(),回调在 then 之后执行
- database - 如何从关系代数中的两个不同表中选择两列
- html - CSS :hover 仅适用于按钮的下半部分