熊猫:如何创建一列来指示值,该值预先在另一列中存在一定数量的行?

时间:2019-11-29 08:33:14

标签: python pandas

我正在尝试确定如何创建一栏来预先指示(X行)何时在另一栏中出现值的下一次出现的熊猫实际上执行以下功能(在这种情况下,X = 3):

df

rowid  event   indicator
1      True    1 # Event occurs
2      False   0
3      False   0
4      False   1 # Starts indicator
5      False   1
6      True    1 # Event occurs
7      False   0

除了在每行中进行迭代/递归循环外:

i = df.index[df['event']==True]
dfx = [df.index[z-X:z] for z in i]
df['indicator'][dfx]=1
df['indicator'].fillna(0)

但这似乎效率低下,是否有更简洁的方法来实现上述示例?谢谢

2 个答案:

答案 0 :(得分:1)

这是使用flatnonzero的基于NumPy的方法:

X = 3
# ndarray of indices where indicator should be set to one
nd_ixs = np.flatnonzero(df.event)[:,None] - np.arange(X-1, -1, -1)
# flatten the indices
ixs = nd_ixs.ravel()
# filter out negative indices an set to 1
df['indicator'] = 0
df.loc[ixs[ixs>=0], 'indicator'] = 1

print(df)

    rowid  event  indicator
0      1   True          1
1      2  False          0
2      3  False          0
3      4  False          1
4      5  False          1
5      6   True          1
6      7  False          0

其中nd_ixs是通过广播方式减去索引而获得的,其中eventTrue,范围最大为X

print(nd_ixs)

array([[-2, -1,  0],
       [ 3,  4,  5]], dtype=int64)

答案 1 :(得分:1)

一种pandasnumpy解决方案:

# Make a variable shift:
def var_shift(series, X):
    return [series] + [series.shift(i) for i in range(-X + 1, 0, 1)]

X = 3
# Set indicator to default to 1
df["indicator"] = 1

# Use pd.Series.where and np.logical_or with the 
#  var_shift function to get a bool array, setting
#  0 when False
df["indicator"] = df["indicator"].where(
    np.logical_or.reduce(var_shift(df["event"], X)),
    0,
)

#    rowid  event  indicator
# 0      1   True          1
# 1      2  False          0
# 2      3  False          0
# 3      4  False          1
# 4      5  False          1
# 5      6   True          1
# 6      7  False          0

In [77]: np.logical_or.reduce(var_shift(df["event"], 3))
Out[77]: array([True, False, False, True, True, True, nan], dtype=object)