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

Tas*_*sos 30 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
Run Code Online (Sandbox Code Playgroud)

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

我想获得符合某些标准的第一行.例子:

  1. 获取A> 3的第一行(返回第2行)
  2. 获取A> 4 AND B> 3的第一行(返回第4行)
  3. 获取A> 3 AND(B> 3 OR C> 2)的第一行(返回第2行)

但是,如果没有任何行满足特定条件,那么我想在我按A(或其他情况由B,C等)对其进行排序后得到第一行

  1. 获取A> 6的第一行(通过A desc命令返回第4行并获取第一行)

我能够通过迭代数据帧来做到这一点(我知道掷骰子:P).所以,我更喜欢用更加pythonic的方式来解决它.

Tgs*_*591 44

对于pandas切片,本教程非常好.一定要检查一下.在某些片段上...要使用条件切片数据框,请使用以下格式:

>>> df[condition]
Run Code Online (Sandbox Code Playgroud)

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

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

    >>> df[df.A > 3].iloc[0]
    A    4
    B    6
    C    3
    Name: 2, dtype: int64
    
    Run Code Online (Sandbox Code Playgroud)

如果你真正想要的是行号,而不是使用iloc,那就是df[df.A > 3].index[0].

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

    >>> df[(df.A > 4) & (df.B > 3)].iloc[0]
    A    5
    B    4
    C    5
    Name: 4, dtype: int64
    
    Run Code Online (Sandbox Code Playgroud)
  2. 获取A> 3 AND(B> 3 OR 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
    
    Run Code Online (Sandbox Code Playgroud)

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

>>> 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
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,它返回第4行.

  • 如果您的数据帧很大,这不是浪费吗?您正在计算整个系列,只是为了提取其第一个元素。 (5认同)

Bou*_*oud 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
Run Code Online (Sandbox Code Playgroud)


Pab*_*rre 8

您可以使用切片和头部处理前 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)

万一没有返回的情况,你可以用 try 或 if 来处理......

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


ZeF*_*Zhu 7

对于“一旦找到满足要求的第一行/记录就返回值并且迭代其他行”这一点,以下代码将起作用:

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

它比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)
Run Code Online (Sandbox Code Playgroud)

正如“镜子”问题的答案中提到的,pandas.Series.idxmax这也是一个不错的选择。

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

pd_idxmax_func(df, (df.A > 4) & (df.B > 3))
Run Code Online (Sandbox Code Playgroud)