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