pandas - python3 pandas:如何快速找到具有值的最新月份数不为0
问题描述
有如下数据框:
id year month y sinx
1 2019 1 0 1
1 2019 2 0 2
1 2019 3 1 3
1 2019 4 0 4
1 2019 5 0 5
1 2019 6 0 6
1 2019 7 0 7
1 2019 8 2 8
1 2019 9 0 9
1 2019 10 0 10
1 2019 11 0 11
1 2019 12 0 11
1 2020 1 0 12
1 2020 2 0 13
1 2020 3 2 14
1 2020 4 0 15
2 2019 1 0 1
2 2019 2 0 2
2 2019 3 0 3
2 2019 4 0 4
.......
我想获取每个月之前每个 id 值(y 列)不为 0 的月数,如果没有上个月或没有上个月的值不为 0,只需将值设置为-1。
例如作为上面的数据框,我想得到以下结果。此外,Dataframe 大约 5M 很大。速度应该很快:
id year month y sinx num_month
1 2019 1 0 1 -1
1 2019 2 0 2 -1
1 2019 3 1 3 -1
1 2019 4 0 4 1
1 2019 5 0 5 2
1 2019 6 0 6 3
1 2019 7 0 7 4
1 2019 8 2 8 5
1 2019 9 0 9 1
1 2019 10 0 10 2
1 2019 11 0 11 3
1 2019 12 0 11 4
1 2020 1 0 12 5
1 2020 2 0 13 6
1 2020 3 2 14 7
1 2020 4 0 15 1
2 2019 1 0 1 -1
2 2019 2 0 2 -1
2 2019 3 1 3 -1
2 2019 4 0 4 1
.......
解决方案
获取累积计数没问题,但获取-1
值的逻辑有点棘手。这些都是矢量化的 pandas 方法,因此它应该在数百万行上都可以执行:
- 您可以获取必要的
groupby
列以及cumsum
y
cumcount()
- 但是,您想再做
cumcount
一行,所以我修复了每组的最后一行np.where()
- 然后稍微棘手的部分是将值更改为
-1
. 我使用与前面步骤类似的技术来实现它,最终根据一些条件mask
将相关值更改为。-1
m = df.groupby(['id', 'y', df['y'].cumsum()]).cumcount() + 1 ########## setup you base getting cumcount
df['num_month'] = np.where((m == 1) & (m.shift() > 1), m.shift() + 1, m).astype(int) # extend cumcount one further row per group for first line of code
s1 = df.groupby('id').transform('idxmin').iloc[:,0] ############## get index location of first value per group and return as series with same length
s2 = df.groupby(['id', (df['y'] > 0).cumsum()]).transform('idxmin').iloc[:,0] ######### get index location of first non-zero value per group and return as series with same length
df['num_month'] = df['num_month'].mask((s1 == s2) | (s1 == s2.shift()), -1) ########### using s1 and s2 conditions, update the necessary rows to -1
df
Out[1]:
id year month y sinx num_month
0 1 2019 1 0 1 -1
1 1 2019 2 0 2 -1
2 1 2019 3 1 3 -1
3 1 2019 4 0 4 1
4 1 2019 5 0 5 2
5 1 2019 6 0 6 3
6 1 2019 7 0 7 4
7 1 2019 8 2 8 5
8 1 2019 9 0 9 1
9 1 2019 10 0 10 2
10 1 2019 11 0 11 3
11 1 2019 12 0 11 4
12 1 2020 1 0 12 5
13 1 2020 2 0 13 6
14 1 2020 3 2 14 7
15 1 2020 4 0 15 1
16 2 2019 1 0 1 -1
17 2 2019 2 0 2 -1
18 2 2019 3 1 3 -1
19 2 2019 4 0 4 1
推荐阅读
- c# - Ef core 为名称 *ID1 的导航属性创建附加列
- sql-server - 如何使用 OPENROWSET 在 SELECT 语句中选择动态列
- java - Spring 我怎样才能只取给定的两个参数之一?
- python - 在 __init__ 中使用 Django 表单中的自定义约束验证输入的数据
- python-3.x - 关于解析奇怪 XML 树的 def 函数的困惑
- python - 使用 Python 转换列表
- r - 具有多个预测变量的多个逻辑回归代码的问题
- javascript - 在本地加载一个 Tensorflow.js 模型
- google-sheets - 如何通过将 2 列作为约束来找到谷歌表格中值的平均值?
- python - 获取python3:代码在iMac上成功运行后无法打开文件和Errno 2错误