如何获取pandas DataFrame的第一个索引,其中多个未定义列不为空?

4

我有一个包含多列的数据帧。我想获取以下条件的第一行索引:

  • 列A的值不为null
  • 还存在至少n个其他的列其值也不为null

例如:如果我的数据帧如下所示:

          Date          A             B      C     D
0   2015-01-02          NaN           1      1    NaN
1   2015-01-02          NaN           2      2    NaN
2   2015-01-02          NaN           3      3    NaN
3   2015-01-02          1            NaN     4    NaN
5   2015-01-02          NaN           2      NaN  NaN
6   2015-01-03          1            NaN     6    NaN
7   2015-01-03          1             1      6    NaN
8   2015-01-03          1             1      6     8

如果 n=1,我会得到3。

如果 n=2,我会得到7。

如果 n=3,我会得到8。


为什么当n=1时,你会得到6而不是3? - Scott Boston
对不起,你是正确的,我已经编辑了帖子。 - astudentofmaths
2个回答

4

以下是一种获取不同n的索引的方法:

def numpy_approach(df, reference='A'):
    df0 = df.iloc[:,df.columns != 'Date']
    valid_mask = df0.columns != reference
    mask = ~np.isnan(df0.values)
    count = mask[:,valid_mask].sum(1) * mask[:,(~valid_mask).argmax()]
    idx0 = np.searchsorted(np.maximum.accumulate(count),[1,2,3])
    return df.index[idx0]

样例运行 -

In [555]: df
Out[555]: 
         Date    A    B    C    D
0  2015-01-02  NaN  1.0  1.0  NaN
1  2015-01-02  NaN  2.0  2.0  NaN
2  2015-01-02  NaN  3.0  3.0  NaN
3  2015-01-02  1.0  NaN  4.0  NaN
5  2015-01-02  NaN  2.0  NaN  NaN
6  2015-01-03  1.0  NaN  6.0  NaN
7  2015-01-03  1.0  1.0  6.0  NaN
8  2015-01-03  1.0  1.0  6.0  8.0

In [556]: numpy_approach(df, reference='A')
Out[556]: Int64Index([3, 7, 8], dtype='int64')

In [557]: numpy_approach(df, reference='B')
Out[557]: Int64Index([0, 7, 8], dtype='int64')

In [558]: numpy_approach(df, reference='C')
Out[558]: Int64Index([0, 7, 8], dtype='int64')

In [568]: numpy_approach(df, reference='D')
Out[568]: Int64Index([8, 8, 8], dtype='int64')

我在运行时遇到了以下错误:result = getitem(key) IndexError: index 50 is out of bounds for axis 1 with size 50 - astudentofmaths
@Arty,是否有可能出现不是所有列都为空的情况?我刚刚编辑了一些代码。你能否使用它并告诉我在哪一行可能会出现错误? - Divakar
是的,我没有明确那种情况。我也没有说明目标列不是A而是B的情况,对于最后一种情况该怎么办? - astudentofmaths
不,我的意思是使用B列作为参考,并且在B列之前和之后的所有其他列。 - astudentofmaths
@Arty,你的表格中有“日期”这一列吗?如果是的话,你会不会想要在计算中跳过该列? - Divakar
显示剩余2条评论

3
您可以首先通过选择 A 列中不为 NaN 的行,并按 loc 列对数据进行计数,然后对每行的非空值使用 notnull 函数进行求和,并在 A 列上减去 1
最后使用布尔掩码和 idxmax 函数。
a = df.loc[df['A'].notnull(), 'A':].notnull().sum(axis=1).sub(1)
print (a)
3    1
6    1
7    2
8    3
dtype: int64

N = 1
print ((a == N).idxmax())
3

N = 2
print ((a == N).idxmax())
7

N = 3
print ((a == N).idxmax())
8

print (df.loc[df['A'].notnull(), 'A':])
     A    B    C    D
3  1.0  NaN  4.0  NaN
6  1.0  NaN  6.0  NaN
7  1.0  1.0  6.0  NaN
8  1.0  1.0  6.0  8.0

你的答案只适用于A列是第一列的情况,但如果之前还有其他列呢? - astudentofmaths
嗯,你是要从A列开始数到df的末尾吗?(B,C,D, ... 列?) - jezrael
在你的示例中,列A是第二列,print (df.loc[df['A'].notnull(), 'A':])不会返回计数的列(还有一列A始终具有非 NaN 值,所以要减去它的值,可以使用sub(1))。 - jezrael
我觉得你误解了我的评论。我的意思是,如果目标列不再是A而是B,例如,在A之前和之后还有其他列呢? 如果A列中没有1而是其他内容会怎样? - astudentofmaths
它也很好用。print(df.loc[df['B'].notnull(), 'B':])并获取从B到结束的所有列,如果还需要开始和结束的列,则使用print (df[df['B'].notnull()]) - jezrael

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