Python 计算表中当前行之前的空格数

Python 计算表中当前行之前的空格数,python,pandas,Python,Pandas,我有一个数据框,其中一行为空,表示一行是否为NaN。我想生成一个新功能,用于统计按id分组的每组记录中当前行之前的NaN行数 下面是一个例子: import pandas as pd is_blank = [0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1] id = [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2] outval = [0, 0, 1, 2, 0, 1, 2, 0, 0, 0, 0] test_df = pd.DataFrame({'id': i

我有一个数据框,其中一行
为空
,表示一行是否为
NaN
。我想生成一个新功能,用于统计按
id
分组的每组记录中当前行之前的
NaN
行数

下面是一个例子:

import pandas as pd
is_blank = [0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1]
id = [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2]
outval = [0, 0, 1, 2, 0, 1, 2, 0, 0, 0, 0]
test_df = pd.DataFrame({'id': id, 'is_blank': is_blank, 'outval': outval})
以下是玩具数据集的外观。我想生成
outval
outval[3]
是2,因为它前面有两个空格。然后,
outval[4]
重置为零,因为该行前面没有空行

In[2]: test_df
Out[2]: 
    id  is_blank  outval
0    1         0       0
1    1         1       0
2    1         1       1
3    1         0       2
4    1         1       0
5    1         1       1
6    1         1       2
7    2         0       0
8    2         0       0
9    2         0       0
10   2         1       0
目前我正在尝试某种形式的累积计数,如:

In[3]: test_df.groupby(['id'])['is_blank'].cumsum().shift(1)
Out[3]: 
0     NaN
1     0.0
2     1.0
3     2.0
4     2.0
5     3.0
6     4.0
7     5.0
8     0.0
9     0.0
10    0.0
但显然,计数器不会在组内重置,并最终计算所有空白行。我正在查看
扩展\u apply
选项,但无法完全理解其工作原理


关于如何有效解决此问题,您有什么想法吗?

您可以基于
is\u blank
创建另一个组变量,以重置总和:

细分:

矢量化方法

b = np.append(0, test_df.is_blank.values[:-1])
i = test_df.id.values

bc = b.cumsum()
w1 = np.where(b == 0)[0]
w2 = np.append(0, np.where(i[:-1] != i[1:])[0] + 1)
bd2 = bc[w2].repeat(np.diff(np.append(r[w2], k)))
bd1 = bc[w1].repeat(np.diff(np.append(r[w1], k)))

test_df.assign(outval=bc - np.fmax(bd1, bd2))

    id  is_blank  outval
0    1         0       0
1    1         1       0
2    1         1       1
3    1         0       2
4    1         1       0
5    1         1       1
6    1         1       2
7    2         0       0
8    2         0       0
9    2         0       0
10   2         1       0
这一点是为了找到发生“重置”的位置。即当
id
发生变化且
为空时
为零

bc
设为
为空
的累积和,然后减去适当的值以“重置”


对于不那么直观的代码的价格。。。您可以获得更快的运行时间

原始时间测试


这个答案给出了这个测试用例的奇怪输出。假设只有一个
id
<代码>为空=[0,1,0,1,0,0,1,0,1,1,0,0,0,0,0,0]<代码>输出值=[0,0,1,0,1,1,0,1,0,1,1,1,1,1,1];但是,所需的输出:
outval=[0,0,1,0,1,0,1,0,1,0,0]
1之后有多个0的情况下,它似乎会失败。请尝试此
test_df['outval']=(test_df.groupby([test_df.id,(test_df.is_blank.diff()!=0.cumsum()))。is_blank.cumsum()。test_df.id)。groupby(test_df.id)。shift())。na(0))
@Psiodom:这很有效。我可以看出前面的那个错误在哪里。是否要使用此解决方案更新主答案?
# create a group variable whose id increases when the blanks are not consecutive
g = (test_df.is_blank.diff() != 0).cumsum()
g

#0     1
#1     2
#2     2
#3     3
#4     4
#5     4
#6     4
#7     5
#8     5
#9     5
#10    6
#Name: is_blank, dtype: int64

# group data frame on both id and g, then do cumsum on the is_blank column
test_df.groupby([test_df.id, g]).is_blank.cumsum().groupby(test_df.id).shift().fillna(0)

#0     0.0
#1     0.0
#2     1.0
#3     2.0
#4     0.0
#5     1.0
#6     2.0
#7     0.0
#8     0.0
#9     0.0
#10    0.0
#Name: is_blank, dtype: float64
b = np.append(0, test_df.is_blank.values[:-1])
i = test_df.id.values

bc = b.cumsum()
w1 = np.where(b == 0)[0]
w2 = np.append(0, np.where(i[:-1] != i[1:])[0] + 1)
bd2 = bc[w2].repeat(np.diff(np.append(r[w2], k)))
bd1 = bc[w1].repeat(np.diff(np.append(r[w1], k)))

test_df.assign(outval=bc - np.fmax(bd1, bd2))

    id  is_blank  outval
0    1         0       0
1    1         1       0
2    1         1       1
3    1         0       2
4    1         1       0
5    1         1       1
6    1         1       2
7    2         0       0
8    2         0       0
9    2         0       0
10   2         1       0