我有一组具有零值头尾行的DataFrame。我想删除这些零值行并保持它们之间的范围。
例如,给定此DataFrame:
x
0 0
1 0
2 1
3 0
4 3
5 1
6 0
7 0
我想要一个返回这个的函数:
x
2 1
3 0
4 3
5 1
请注意,第3行的零值尚未丢失。我不想删除所有零,只有头部和尾部。如何用熊猫做到这一点?
使用:
df = df[df['x'].cumsum().mul(df['x'].iloc[::-1].cumsum()).ne(0)]
print (df)
x
2 1
3 0
4 3
5 1
说明:
获得cumsum
专栏:
print (df['x'].cumsum())
0 0
1 0
2 1
3 1
4 4
5 5
6 5
7 5
Name: x, dtype: int64
反转列和cumsum
:
print (df['x'].iloc[::-1].cumsum())
7 0
6 0
5 1
4 4
3 4
2 5
1 5
0 5
Name: x, dtype: int64
Series.mul
的倍数:
print (df['x'].cumsum().mul(df['x'].iloc[::-1].cumsum()))
0 0
1 0
2 5
3 4
4 16
5 5
6 0
7 0
Name: x, dtype: int64
并检查ne
的(!=)
0
不相等:
print (df['x'].cumsum().mul(df['x'].iloc[::-1].cumsum()).ne(0))
0 False
1 False
2 True
3 True
4 True
5 True
6 False
7 False
Name: x, dtype: bool
最后一次过滤由boolean indexing
。
谢谢@Wen的另一个解决方案:
df[(df.x.eq(0).cumprod().eq(0))&(df.x[::-1].eq(0).cumprod().eq(0))]
它也很有用。 nonzero
将给出系列中非零元素的索引。访问元组的第一个和最后一个索引将生成预期输出
import pandas as pd
df2=pd.DataFrame({'cols':[0,0,1,0,3,1,0,0]})
non_zero_index = df2.cols.nonzero()[0]
start, end = non_zero_index[0],non_zero_index[-1]
df2.loc[start:end]
cols
2 1
3 0
4 3
5 1
对于具有少量零的大型数组,手动迭代将比布尔索引更有效。例如,通过next
和enumerate
的生成器表达式:
start = next(idx for idx, val in enumerate(df['x']) if val != 0)
end = -next(idx for idx, val in enumerate(df['x'].iloc[::-1]) if val != 0)
res = df['x'].iloc[start:end]
2 1
3 0
4 3
5 1
Name: x, dtype: int64
我也会把我的马放在这场比赛中。
Cumsum向前,cumsum向后,如果等于零丢弃则取最小值。
df[np.minimum(df['x'].cumsum(), df['x'][::-1].cumsum()[::-1]).ne(0)]
输出:
x
2 1
3 0
4 3
5 1
受到mad_的启发
df.loc[df.x.mask(df.x==0).first_valid_index():df.x.mask(df.x==0).last_valid_index()]
Out[39]:
x
2 1
3 0
4 3
5 1
d={'x':[0,0,1,2,1,0,0,4,4,0,0]}
df=pd.DataFrame(d)
删除尾零:
i=len(df)-1
x=df['x'][i]
while x==0:
i-=1
x=df['x'][i]
df=df[0:i+1]
删除头部零:
while x==0:
del df['x'][i]
i-=1
x=df['x'][i]
df=df[i:]