【问题标题】:Filtering pandas dataframe by min-max kwargs通过 min-max kwargs 过滤 pandas 数据帧
【发布时间】:2019-03-15 15:15:19
【问题描述】:

我有一个基于用户输入的最小值和最大值的可选 kwargs(总共 8 个)的函数。

例如GR_min, GR_max, GR_N_min, GR_N_max, Hi_min, Hi_max 等...其中数据框列是GRGR_NHi 等...

我希望数据框过滤给定的最小值和最大值,但如果在函数调用中未给出一个或多个值,则将默认最小值-最大值设置为的最小值-最大值列。

例如一些伪代码:

df = pd.DataFrame({'GR': [1, 2, 3, 4, 2, 3], 
'GR_N': [0.8, 0, 1, 0.6, 0.9, 1], 'Hi':[3, 6, 2, 5, 22, 7]})

得到我:

    GR  GR_N    Hi
0   1   0.8     3
1   2   0.0     6
2   3   1.0     2
3   4   0.6     5
4   2   0.9     22
5   3   1.0     7

我想要一个做这样的事情的函数:

def picker(data, **kwargs):

      data_filtered = data[data['GR'].between(GR_min, GR_max) &
                         data['GR_N'].between(GR_N_min, GR_N_max) &
                         data['Hi'].between(Hi_min, Hi_max)]

      return data_filtered

调用后有输出:

picker(data=df, GR_min=2, GR_max=3, Hi_min=1, Hi_max=6)

    GR  GR_N    Hi
1   2   0.0     6
2   3   1.0     2

除了显式调用数据框的每一列之外,我们使用 **kwargs 本身进行过滤。

有什么办法吗?

【问题讨论】:

    标签: python python-3.x pandas dataframe keyword-argument


    【解决方案1】:

    DataFrame.query 在这里可以很方便,因为它会解析一个包含条件的字符串。因此,从关键字参数构建条件字符串就足够了。

    每个单独的条件都可以构建为:K<=val 用于K_max=val 参数,K>=val 用于K_min=val 参数。要构建列表,必须将每个单独的条件括在括号中 (()),然后与 & 连接。

    代码可以是:

    def picker(data, **kwargs):
        def make_cond(k,v):
            if len(k)<5:
                raise(ValueError('Arg too short {}'.format(k)))
            if k.endswith('_min'):
                return '({}>={})'.format(k[:-4], v)
            elif k.endswith('_max'):
                return '({}<={})'.format(k[:-4], v)
            else:
                raise(ValueError('Unknow arg {}'.format(k)))
        strcond='&'.join((make_cond(k, v) for k,v in kwargs.items()))
        # print(strcond)     # uncomment for traces
        return data.query(strcond)
    

    【讨论】:

    • 此方法为.join((make_cond(k,v)) 调用本身的函数。它输出“strcond”不存在。
    • @HelloToEarth:复制时出现愚蠢的缩进错误。固定。
    【解决方案2】:

    您可以为您的 kwargs 指定一个默认字典,将最小值和最大值指定为 -infinity 和 +infinity,然后使用用户输入覆盖它们。像这样的:

    import numpy as np
    def picker(data, **kwargs):
        d = dict(GR_min=-np.inf, GR_max=np.inf) # ... etc
        kwargs = {**d, **kwargs}
        data_filtered = data[data['GR'].between(kwargs["GR_min"], kwargs["GR_max"])] # ... etc
        return data_filtered
    

    【讨论】:

    • 有没有办法让这个默认字典d 只接受用户指定的值,而不是明确定义所有可能的最小值和最大值?
    • 这就是这种方式会发生的事情 - 默认字典中定义的 kwargs 只会被用户输入的值替换。因此,如果您在没有任何 kwargs 的情况下运行该函数,它将返回所有数据。这就是你想要的吗?
    【解决方案3】:

    对此我有点困惑,根据列中的最小值-最大值进行过滤根本就不是过滤,不是吗?为什么不只根据提供的参数进行过滤?无论如何,这听起来像是默认参数的情况。

    #create the DataFrame
    df = pd.DataFrame({'GR': [1, 2, 3, 4, 2, 3], 
    'GR_N': [0.8, 0, 1, 0.6, 0.9, 1], 'Hi':[3, 6, 2, 5, 22, 7]})
    
    def picker(df, GR_min = None, GR_max = None, GR_N_min = None, GR_N_max = None,
               Hi_min = None, Hi_max = None): #use default arguments
    
               if GR_min == None:
                   GR_min = df['GR'].min()
               if GR_max == None:
                   GR_max = df['GR'].max()
               if GR_N_min == None:
                   GR_N_min = df['GR_N'].min()
               if GR_N_max == None:
                   GR_N_max == df['GR_N'].max()
    
               #filter the DataFrame with masks
               df_out = df.loc[(df['GR'] > GR_min) & (df['GR'] < GR_max) & 
                               (df['GR_N'] > GR_N_min) & (df['GR_N'] < GR_N_max)]
               return df_out
    

    【讨论】:

      猜你喜欢
      • 2017-03-08
      • 1970-01-01
      • 1970-01-01
      • 2022-11-30
      • 1970-01-01
      • 2019-01-06
      • 2022-11-10
      • 2020-07-13
      • 2020-03-18
      相关资源
      最近更新 更多