如何计算从右边开始具有零值的连续列数,直到出现第一个非零元素
How do I calculate the number of consecutive columns with zero values from the right until the first non zero element occurs
假设我有以下数据框:
C1 C2 C3 C4
0 1 2 3 0
1 4 0 0 0
2 0 0 0 3
3 0 3 0 0
然后我想添加另一列,以便它显示从右侧连续出现的零值列的数量。
新列将是:
Cnew
0 1
1 3
2 0
3 2
您可以使用:
df['new'] = df.iloc[:,::-1].cumsum(axis=1).eq(0).sum(axis=1)
print (df)
C1 C2 C3 C4 new
0 1 2 3 0 1
1 4 0 0 0 3
2 0 0 0 3 0
3 0 3 0 0 2
print (df.iloc[:,::-1])
C4 C3 C2 C1
0 0 3 2 1
1 0 0 0 4
2 3 0 0 0
3 0 0 3 0
print (df.iloc[:,::-1].cumsum(axis=1))
C4 C3 C2 C1
0 0 3 5 6
1 0 0 0 4
2 3 3 3 3
3 0 0 3 3
print (df.iloc[:,::-1].cumsum(axis=1).eq(0))
C4 C3 C2 C1
0 True False False False
1 True True True False
2 False False False False
3 True True False False
使用 eq
、cumprod
和 sum
(这与 回答的问题非常相似)
df.iloc[:,::-1].eq(0).cumprod(axis=1).sum(axis=1)
输出:
0 1
1 3
2 0
3 2
dtype: int64
我会在布尔数组上使用 argmax
。另外,如果我直接跳到 numpy
,我可以做得非常快。
(df.values[:, ::-1] != 0).argmax(1)
array([1, 3, 0, 2])
或非常相似
(df.values[:, ::-1].astype(bool)).argmax(1)
array([1, 3, 0, 2])
我可以将它放在新的列中 assign
df.assign(new=(df.values[:, ::-1] != 0).argmax(1))
C1 C2 C3 C4 new
0 1 2 3 0 1
1 4 0 0 0 3
2 0 0 0 3 0
3 0 3 0 0 2
或原地添加新列
df['new'] = (df.values[:, ::-1] != 0).argmax(1)
df
C1 C2 C3 C4 new
0 1 2 3 0 1
1 4 0 0 0 3
2 0 0 0 3 0
3 0 3 0 0 2
时机
我们通过减少必要的工作来减少时间。我们只需要找到第一个非零的位置即可。
# My first variant
%timeit df.assign(new=(df.values[:, ::-1] != 0).argmax(1))
# My second variant
%timeit df.assign(new=(df.values[:, ::-1].astype(bool)).argmax(1))
# jezrael's solution
%timeit df.assign(new=df.iloc[:,::-1].cumsum(1).eq(0).sum(1))
# numpy version of jezrael's solution
%timeit df.assign(new=(df.values[:,::-1].cumsum(1) == 0).sum(1))
# Scott Boston's solution
%timeit df.assign(new=df.iloc[:,::-1].eq(0).cumprod(axis=1).sum(axis=1))
# numpy version of Scott Boston's solution
%timeit df.assign(new=(df.values[:,::-1] == 0).cumprod(1).sum(1))
小数据
1000 loops, best of 3: 301 µs per loop
1000 loops, best of 3: 273 µs per loop
1000 loops, best of 3: 770 µs per loop
1000 loops, best of 3: 323 µs per loop
1000 loops, best of 3: 647 µs per loop
1000 loops, best of 3: 324 µs per loop
更大的数据
df = pd.DataFrame(np.random.choice([0, 1], (10000, 100), p=(.7, .3)))
100 loops, best of 3: 6.03 ms per loop
100 loops, best of 3: 5.3 ms per loop
100 loops, best of 3: 16.9 ms per loop
100 loops, best of 3: 9 ms per loop
100 loops, best of 3: 10.7 ms per loop
100 loops, best of 3: 10.1 ms per loop
假设我有以下数据框:
C1 C2 C3 C4
0 1 2 3 0
1 4 0 0 0
2 0 0 0 3
3 0 3 0 0
然后我想添加另一列,以便它显示从右侧连续出现的零值列的数量。 新列将是:
Cnew
0 1
1 3
2 0
3 2
您可以使用:
df['new'] = df.iloc[:,::-1].cumsum(axis=1).eq(0).sum(axis=1)
print (df)
C1 C2 C3 C4 new
0 1 2 3 0 1
1 4 0 0 0 3
2 0 0 0 3 0
3 0 3 0 0 2
print (df.iloc[:,::-1])
C4 C3 C2 C1
0 0 3 2 1
1 0 0 0 4
2 3 0 0 0
3 0 0 3 0
print (df.iloc[:,::-1].cumsum(axis=1))
C4 C3 C2 C1
0 0 3 5 6
1 0 0 0 4
2 3 3 3 3
3 0 0 3 3
print (df.iloc[:,::-1].cumsum(axis=1).eq(0))
C4 C3 C2 C1
0 True False False False
1 True True True False
2 False False False False
3 True True False False
使用 eq
、cumprod
和 sum
(这与
df.iloc[:,::-1].eq(0).cumprod(axis=1).sum(axis=1)
输出:
0 1
1 3
2 0
3 2
dtype: int64
我会在布尔数组上使用 argmax
。另外,如果我直接跳到 numpy
,我可以做得非常快。
(df.values[:, ::-1] != 0).argmax(1)
array([1, 3, 0, 2])
或非常相似
(df.values[:, ::-1].astype(bool)).argmax(1)
array([1, 3, 0, 2])
我可以将它放在新的列中 assign
df.assign(new=(df.values[:, ::-1] != 0).argmax(1))
C1 C2 C3 C4 new
0 1 2 3 0 1
1 4 0 0 0 3
2 0 0 0 3 0
3 0 3 0 0 2
或原地添加新列
df['new'] = (df.values[:, ::-1] != 0).argmax(1)
df
C1 C2 C3 C4 new
0 1 2 3 0 1
1 4 0 0 0 3
2 0 0 0 3 0
3 0 3 0 0 2
时机
我们通过减少必要的工作来减少时间。我们只需要找到第一个非零的位置即可。
# My first variant
%timeit df.assign(new=(df.values[:, ::-1] != 0).argmax(1))
# My second variant
%timeit df.assign(new=(df.values[:, ::-1].astype(bool)).argmax(1))
# jezrael's solution
%timeit df.assign(new=df.iloc[:,::-1].cumsum(1).eq(0).sum(1))
# numpy version of jezrael's solution
%timeit df.assign(new=(df.values[:,::-1].cumsum(1) == 0).sum(1))
# Scott Boston's solution
%timeit df.assign(new=df.iloc[:,::-1].eq(0).cumprod(axis=1).sum(axis=1))
# numpy version of Scott Boston's solution
%timeit df.assign(new=(df.values[:,::-1] == 0).cumprod(1).sum(1))
小数据
1000 loops, best of 3: 301 µs per loop
1000 loops, best of 3: 273 µs per loop
1000 loops, best of 3: 770 µs per loop
1000 loops, best of 3: 323 µs per loop
1000 loops, best of 3: 647 µs per loop
1000 loops, best of 3: 324 µs per loop
更大的数据
df = pd.DataFrame(np.random.choice([0, 1], (10000, 100), p=(.7, .3)))
100 loops, best of 3: 6.03 ms per loop
100 loops, best of 3: 5.3 ms per loop
100 loops, best of 3: 16.9 ms per loop
100 loops, best of 3: 9 ms per loop
100 loops, best of 3: 10.7 ms per loop
100 loops, best of 3: 10.1 ms per loop