基于条件获取Python中数据帧的第一行

基于条件获取Python中数据帧的第一行,python,pandas,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 原始表更复杂,有更多的列和行 我想得到满足某些标准的第一行。示例: 获取A

假设我有一个这样的数据帧

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
原始表更复杂,有更多的列和行

我想得到满足某些标准的第一行。示例:

  • 获取A>3的第一行(返回第2行)
  • 获取A>4和B>3的第一行(返回第4行)
  • 获取A>3且(B>3或C>2)的第一行(返回第2行)
  • 但是,如果没有任何一行满足特定的标准,那么我希望在按A(或其他情况下按B、C等)降序排序后得到第一行

  • 获取A>6的第一行(通过按desc排序返回第4行并获取第一行)

  • 我可以通过在数据帧上迭代来实现(我知道craps:p)。因此,我更喜欢用一种更具python风格的方法来解决它。

    对于现有的匹配项,请使用
    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
    

    您可以使用切片和头部处理前3项:

  • df[df.A>=4]。头(1)
  • df[(df.A>=4)和(df.B>=3)]。头(1)
  • df[(df.A>=4)和((df.B>=3)*(df.C>=2))。头(1)
  • 这种情况下,如果没有回来,你可以处理一个尝试或如果

    try:
        output = df[df.A>=6].head(1)
        assert len(output) == 1
    except: 
        output = df.sort_values('A',ascending=False).head(1)
    
    这是一个非常好的熊猫切片。一定要检查一下。在一些片段上。。。要使用条件切片数据帧,请使用以下格式:

    >>> df[condition]
    
    这将返回数据帧的一个片段,您可以使用
    iloc
    对其进行索引。以下是您的示例:

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

  • 如果您真正想要的是行号,而不是使用
    iloc
    ,那么它应该是
    df[df.A>3]。索引[0]

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

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

  • 现在,对于上一个案例,我们可以编写一个函数来处理返回降序排序帧的默认情况:

    >>> 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行。

    对于“在找到满足要求的第一行/记录时立即返回值,而不是迭代其他行时,以下代码将起作用:

    def pd_iter_func(df):
    对于df.itertuples()中的行:
    #在这里定义您的标准
    如果第A行>4行,第B行>3行:
    返回行
    
    对于大型数据帧,它比布尔索引更有效

    为了使上述函数更适用,可以实现lambda函数:

    def pd_iter_func(df:DataFrame,条件:可调用[[NamedTuple],bool])->可选[NamedTuple]:
    对于df.itertuples()中的行:
    如果条件(行):
    返回行
    pd_iter_func(df,lambda行:A行>4行,B行>3行)
    

    如中所述,
    pandas.Series.idxmax
    也是一个不错的选择

    def pd_idxmax_func(测向,掩码):
    返回df.loc[mask.idxmax()]
    pd_idxmax_func(df,(df.A>4)和(df.B>3))
    
    第一行A>4是4,您能检查一下您正在搜索的测试吗?@Boud对此表示抱歉。类型错误:(因此,@Kartik我将使用布尔索引,如果返回的数据帧为空,那么我将手动对其进行排序并获得第一行?这是最合适的方法?布尔索引可能比您想要的要多,因为它必须贯穿整个数据帧。如果第一行是您想要的,您应该能够立即找到,regardle数据帧大小的ss。如果您的数据帧非常大,这不是浪费吗?您正在计算整个系列,只是为了提取其第一个元素。我喜欢itertuples()。但是对于idxmax(),在运行idxmax()之前,不是每行的最大值吗?
    >>> df[(df.A > 3) & ((df.B > 3) | (df.C > 2))].iloc[0]
    A    4
    B    6
    C    3
    Name: 2, dtype: int64
    
    >>> 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