根据条件获取Python Pandas中的第一行数据帧

时间:2016-11-17 16:27:04

标签: python pandas

假设我有一个像这样的数据框

import pandas as pd
df = pd.DataFrame([[1, 2, 1], [1, 3, 2], [4, 6, 3], [4, 3, 4], [5, 4, 5]], columns=['A', 'B', 'C'])

>> df
   A  B  C
0  1  2  1
1  1  3  2
2  4  6  3
3  4  3  4
4  5  4  5

原始表格更复杂,列数和行数更多。

我希望获得符合某些条件的第一行。例子:

  1. 获取A>的第一行3(返回第2行)
  2. 获取A>的第一行4和B> 3(返回第4行)
  3. 获取A>的第一行3 AND(B> 3或C> 2)(返回第2行)
  4. 但是,如果没有任何行符合特定标准,那么我想在按A(或其他情况用B,C等)对其进行排序之后得到第一行

    1. 获取A>的第一行6(通过A desc命令返回第4行并获得第一个)
    2. 我能够通过迭代数据帧来实现(我知道掷骰子:P)。所以,我更喜欢用更加pythonic的方式来解决它。

4 个答案:

答案 0 :(得分:36)

对于pandas切片来说,

This tutorial非常好。一定要检查一下。在某些片段上...要使用条件切片数据帧,请使用以下格式:

>>> df[condition]

这将返回您可以使用iloc索引的数据帧的一部分。以下是您的示例:

  1. 获取A>的第一行3(返回第2行)

    >>> df[df.A > 3].iloc[0]
    A    4
    B    6
    C    3
    Name: 2, dtype: int64
    
  2. 如果你真正想要的是行号,而不是iloc,那就是df[df.A > 3].index[0]

    1. 获取A>的第一行4和B> 3:

      >>> df[(df.A > 4) & (df.B > 3)].iloc[0]
      A    5
      B    4
      C    5
      Name: 4, dtype: int64
      
    2. 获取A>的第一行3 AND(B> 3或C> 2)(返回第2行)

      >>> df[(df.A > 3) & ((df.B > 3) | (df.C > 2))].iloc[0]
      A    4
      B    6
      C    3
      Name: 2, dtype: int64
      
    3. 现在,在你的上一个案例中,我们可以编写一个函数来处理返回降序排序帧的默认情况:

      >>> def series_or_default(X, condition, default_col, ascending=False):
      ...     sliced = X[condition]
      ...     if sliced.shape[0] == 0:
      ...         return X.sort_values(default_col, ascending=ascending).iloc[0]
      ...     return sliced.iloc[0]
      >>> 
      >>> series_or_default(df, df.A > 6, 'A')
      A    5
      B    4
      C    5
      Name: 4, dtype: int64
      

      正如所料,它返回第4行。

答案 1 :(得分:11)

对于现有比赛,请使用query

df.query(' A > 3' ).head(1)
Out[33]: 
   A  B  C
2  4  6  3

df.query(' A > 4 and B > 3' ).head(1)
Out[34]: 
   A  B  C
4  5  4  5

df.query(' A > 3 and (B > 3 or C > 2)' ).head(1)
Out[35]: 
   A  B  C
2  4  6  3

答案 2 :(得分:2)

你可以用切片和头部来处理前3个项目:

  1. df[df.A>=4].head(1)
  2. df[(df.A>=4)&(df.B>=3)].head(1)
  3. df[(df.A>=4)&((df.B>=3) * (df.C>=2))].head(1)
  4. 如果没有任何回复的情况你可以通过试试或if ...来处理

    try:
        output = df[df.A>=6].head(1)
        assert len(output) == 1
    except: 
        output = df.sort_values('A',ascending=False).head(1)
    

答案 3 :(得分:0)

对于“一旦找到符合要求的第一行/记录并立即返回值,并且迭代其他行”,以下代码将起作用:

def pd_iter_func(df):
    for row in df.itertuples():
        # Define your criteria here
        if row.A > 4 and row.B > 3:
            return row

对于大型数据帧,它比Boolean Indexing更有效率。

为使以上功能更适用,可以实现lambda函数:

def pd_iter_func(df: DataFrame, criteria: Callable[[NamedTuple], bool]) -> Optional[NamedTuple]:
    for row in df.itertuples():
        if criteria(row):
            return row

pd_iter_func(df, lambda row: row.A > 4 and row.B > 3)

the answer to the 'mirror' question中所述,pandas.Series.idxmax也是不错的选择。

def pd_idxmax_func(df, mask):
    return df.loc[mask.idxmax()]

pd_idxmax_func(df, (df.A > 4) & (df.B > 3))