在pandas DataFrame中找到每列的第一个非零值

16

如何以明智的方式获取DataFrame每列中第一个非零元素的值和索引(从上到下)?

import pandas as pd

df = pd.DataFrame([[0, 0, 0],
                   [0, 10, 0],
                   [4, 0, 0],
                   [1, 2, 3]],
                  columns=['first', 'second', 'third'])

print(df.head())

#    first  second  third
# 0      0       0      0
# 1      0      10      0
# 2      4       0      0
# 3      1       2      3

我的目标是什么:

#        value  pos
# first      4    2
# second    10    1
# third      1    3
4个回答

23

你需要使用idxmax函数来获取最大值的第一个位置。然而,你需要找到“不等于零”的最大值。

df.ne(0).idxmax()

first     2
second    1
third     3
dtype: int64

我们可以将此与lookupassign结合使用。
df.ne(0).idxmax().to_frame('pos').assign(val=lambda d: df.lookup(d.pos, d.index))

        pos  val
first     2    4
second    1   10
third     3    3

同样的答案,稍微包装了一下。

m = df.ne(0).idxmax()
pd.DataFrame(dict(pos=m, val=df.lookup(m, m.index)))

        pos  val
first     2    4
second    1   10
third     3    3

idxmax()会给出最大值,这个最大值恰好是该列(自上而下)的第一个值。那么,检测第一个非零值的最佳方法是什么? - Meruemu
如果所有值都是零,那么这并不起作用。在这种情况下,您将得到与第一个非零值(pos=0)相同的答案。 - shaneb
如果所有值都为零,则零是最大值。 - piRSquared

4

以下是一种详细的方法,如果您的非零值通常出现在大型数组的开头,则应该更快:

import pandas as pd

df = pd.DataFrame([[0, 0, 0],[0, 10, 0],[4, 0, 0],[1, 2, 3]],
                  columns=['first', 'second', 'third'])

res = [next(((j, i) for i, j in enumerate(df[col]) if j != 0), (0, 0)) for col in df]

df_res = pd.DataFrame(res, columns=['value', 'position'], index=df.columns)

print(df_res)

        value  position
first       4         2
second     10         1
third       3         3

3

我将使用,索引用于行号和列号

df[df.eq(df.max(1),0)&df.ne(0)].stack()
Out[252]: 
1  second    10.0
2  first      4.0
3  third      3.0
dtype: float64

2
您也可以使用Numpy的nonzero函数来实现此功能。
positions = [df[col].to_numpy().nonzero()[0][0] for col in df]
df_res = pd.DataFrame({'value': df.to_numpy()[(positions, range(3))], 
                       'position': positions}, index=df.columns)
print(df_res)

        value  position
first       4         2
second     10         1
third       3         3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接