使用 Pandas 查找每行的第一个 NaN 值并返回列名

8

I have a dataframe like this

>>df1 = pd.DataFrame({'A': ['1', '2', '3', '4','5'],
              'B': ['1', '1', '1', '1','1'],
              'C': ['c', 'A1', None, 'c3',None],
              'D': ['d0', 'B1', 'B2', None,'B4'],
              'E': ['A', None, 'S', None,'S'],
              'F': ['3', '4', '5', '6','7'],
              'G': ['2', '2', None, '2','2']})
>>df1

   A  B     C     D     E  F     G
0  1  1     c    d0     A  3     2
1  2  1    A1    B1  None  4     2
2  3  1  None    B2     S  5  None
3  4  1    c3  None  None  6     2
4  5  1  None    B4     S  7     2

我删除包含NaN值的行。df2 = df1.dropna()

   A  B     C     D     E  F     G   
1  2  1    A1    B1  None  4     2
2  3  1  None    B2     S  5  None
3  4  1    c3  None  None  6     2
4  5  1  None    B4     S  7     2

这是一个由于数据中包含NaN值而被删除的数据框。但是,我想知道为什么它们会被删除?哪一列是导致该行被删除的“第一个NaN值列”?我需要报告被删除的原因。

输出应为:

['E','C','D','C']

我知道可以通过对每一列使用dropna,然后将其记录为原因来实现,但这真的不够高效。

有没有更高效的方法来解决这个问题呢? 谢谢。


使用None而不是NaN是否有任何原因?对于您的问题的答案可能取决于这个... - MaxU - stand with Ukraine
好的...只是举个例子。我没有意识到它们是不同的。无论如何,np.nan没问题。 - user2775128
2个回答

15

我认为您可以通过DataFrame.isnull创建布尔数据框,然后使用布尔索引筛选掩码中至少有一个True的行,并使用any方法和最后一个idxmax方法 - 您将获得第一个True值的列名:

booldf = df1.isnull()
print (booldf)
       A      B      C      D      E      F      G
0  False  False  False  False  False  False  False
1  False  False  False  False   True  False  False
2  False  False   True  False  False  False   True
3  False  False  False   True   True  False  False
4  False  False   True  False  False  False  False

print (booldf.any(axis=1))
0    False
1     True
2     True
3     True
4     True
dtype: bool

print (booldf[booldf.any(axis=1)].idxmax(axis=1))
1    E
2    C
3    D
4    C
dtype: object

1
哦,那是一个更好的方法,我总是忘记 anyall + 1。 - juanpa.arrivillaga
你还可以免费获得相应的行。 - juanpa.arrivillaga
@juanpa.arrivillaga - 谢谢。 - jezrael
谢谢!这就是我需要的!还要感谢@juanpa.arrivillaga - user2775128

0

我会结合使用 itertoolsnumpy.where,以及 pd.DataFrame.isnull

>>> df1.isnull()
       A      B      C      D      E      F      G
0  False  False  False  False  False  False  False
1  False  False  False  False   True  False  False
2  False  False   True  False  False  False   True
3  False  False  False   True   True  False  False
4  False  False   True  False  False  False  False
>>> from itertools import *
>>> r,c = np.where(df1.isnull().values)
>>> first_cols = [next(g)[1] for _, g in groupby(izip(r,c), lambda t:t[0])]
>>> df1.columns[first_cols]
Index([u'E', u'C', u'D', u'C'], dtype='object')
>>> 

对于 Python 2,请使用 itertools 中的 izip,而在 Python 3 中则直接使用内置的 zip


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