【问题标题】:Get first column value in Pandas DataFrame where row matches condition获取 Pandas DataFrame 中行匹配条件的第一列值
【发布时间】:2019-01-18 17:18:14
【问题描述】:

假设我有一个如下所示的 pandas 数据框:

   color  number
0    red       3
1   blue       4
2  green       2
3   blue       2

我想从数字列中获取第一个值,其中颜色列的值为'blue',在这种情况下将返回4

我知道这可以使用loc 来完成,如下所示:

df[df['color'] == 'blue']['number'][0]

鉴于我只需要第一次出现,我想知道是否有任何更优化的方法。

【问题讨论】:

    标签: python pandas performance dataframe optimization


    【解决方案1】:

    使用idxmax

    df.loc[(df['color'] == 'blue').idxmax(),'number']
    Out[698]: 4
    

    【讨论】:

    • 在调用 idxmax 之前,这里需要一个 if 语句。
    • @coldspeed 喜欢这个? df.loc[if (df['color'] == 'blue').idxmax(),'number']
    • @UBears 不,例如,请参阅下面的答案。或者,if (df['color'] == 'blue').any(): ...
    • @coldspeed 所以我需要一个 if 语句来检查列是否为空?
    • @UBears 不,是检查“蓝色”是否存在。否则,如果蓝色不存在,idxmax 总是返回 0,此时返回的结果应该为空。那有意义吗?再次,您可以查看我的答案示例和答案比较
    【解决方案2】:

    使用head——如果颜色存在则返回第一行,否则返回空的Series

    col = 'blue'
    df.query('color == @col').head(1).loc[:, 'number']
    
    1    4
    Name: number, dtype: int64
    

    或者,要获取单个项目,请使用obj.is_empty

    u = df.query('color == @col').head(1)
    if not u.is_empty:
        print(u.at[u.index[0], 'number'])
    
    # 4
    

    headidxmax 的区别在于无效颜色:

    df.query('color == "blabla"').head(1).loc[:, 'number']
    # Series([], Name: number, dtype: int64)
    
    df.loc[(df['color'] == 'blabla').idxmax(),'number']
    # 3
    

    【讨论】:

      【解决方案3】:

      ilocnp.where 一起使用:

      idx = next(iter(df['number'].iloc[np.where(df['color'].eq('blue'))]), -1)  # 4
      

      请注意,这也可以处理颜色不存在的情况。相比之下,df['color'].eq('orange').idxmax() 给出了0,即使系列中不存在'orange'。上面的逻辑会给出-1

      numba

      我想知道是否有任何更优化的方法,因为我只 永远需要第一次出现。

      是的!如需更有效的解决方案,请参阅Efficiently return the index of the first value satisfying condition in array。 Numba 允许您有效地逐行迭代。在这种情况下,您需要先factorize your strings,以便仅将数字数组提供给 Numba:

      from numba import njit
      
      # factorize series, pd.factorize maintains order,
      # i.e. first item in values gives 0 index
      idx, values = pd.factorize(df['color'])
      idx_search = np.where(values == 'blue')[0][0]
      
      @njit
      def get_first_index_nb(A, k):
          for i in range(len(A)):
              if A[i] == k:
                  return i
          return -1
      
      res = df['number'].iat[get_first_index_nb(idx, 1)]  # 4
      

      当然,对于一次性计算,这是低效的。但是对于连续计算,解决方案可能比检查整个系列/数组是否相等的解决方案更快。

      【讨论】:

        猜你喜欢
        • 2020-09-09
        • 2018-01-20
        • 2022-08-19
        • 2018-07-24
        • 1970-01-01
        • 1970-01-01
        • 2019-02-27
        • 2019-08-18
        • 1970-01-01
        相关资源
        最近更新 更多