代码之家  ›  专栏  ›  技术社区  ›  Trenton McKinney ivirshup

如何为数据帧动态创建不同长度的'&'过滤器

  •  1
  • Trenton McKinney ivirshup  · 技术社区  · 7 年前

    根据来自主数据帧(df)的长度可变的输入(test\u tuple¶ms),生成一个过滤数据帧(filtered\u df)。可能有数百种过滤器组合。

    任职理由:

    我想说的是,这里的一切都能产生预期的产出。也就是说,我不喜欢解决方案1的实现方法,在dict中创建一个虚拟的DataFrame对象,循环会依次过滤和更新这个对象。解决方案1似乎有点混乱,但我需要一些指导来实现更简洁的东西。

    请求:

    有没有办法使用解决方案2中所示的过滤器?

    筛选器格式正确,但为字符串。是否有一种方法来产生过滤器,以便可以如图所示使用?

    输入示例:

    test_tuple = [('Serial Number', [12345]),
                  ('Test Points', ['TestpointA', 'TestpointC']),
                  ('Voltage_1', [3.0, 3.3, 3.6, 0.0]),
                  ('Temperature Setpoint', [0, 60]),
                  ('Slew_1', [200, 400, 800, 1600, 3200, 6400])]
    params = ['sn', 'tp', 'v1', 'temp', 'slew']
    

    代码:

    for i in itertools.product(*[b for _, b in test_tuple]):
         print('\n'.join(f'{a}:{b}' for a, b in zip(params, i)))
         name_params = '_'.join(f'{b}{a}' for a, b in zip(params, i)) 
         filter_t = ' & '.join(f'(self.df["{c[0]}"] == {b})' for b, c in zip(i, test_tuple))
         print(f'filter_t: {filter_t}')
         filter_l = [(c[0], b) for b, c in zip(i, test_tuple)]
    

    筛选器的字符串格式:

    filter_t: (self.df["Test Points"] == 3P3V) & (self.df["Slew_1"] == 5000)
    filter_t: (self.df["Serial Number"] == 2450) & (self.df["Test Points"] == 3P3V) & (self.df["Voltage_1"] == 11.6) & (self.df["Temperature Setpoint"] == 25.0) & (self.df["Slew_1"] == 5000)
    

    过滤器格式:

    filter_l: [('Test Points', '3P3V_Edge'), ('Slew_1', 200)]
    filter_l: [('Serial Number', 1234), ('Test Points', '3P3V'), ('Voltage_1', 11.6), ('Temperature Setpoint', 25.0), ('Slew_1', 200)]
    

    filtered_df = {1: df}
    for x in filter_l:
         filtered_df[1] = (filtered_df[1].loc[(filtered_df[1][f'{x[0]}'] == x[1])])
    

    解决方案2-可能吗?:

    df_filter = self.df.loc[filter_t]
    

    过滤器示例:

    df_filter = self.df.loc[(self.df['Serial Number'] == 1234) &
                            (self.df['Test Points'] == '3P3V') &
                            (self.df['Voltage_1'] == 11.6) &
                            (self.df['Temperature Setpoint'] == 25.0) &
                            (self.df['Slew'] == 200)]
    

    最终解决方案@John Zwinck-Thx:

    filter_t = ' & '.join(f'{c[0]} == "{b}"' for b, c in zip(i, test_tuple))
    filtered_df = df.loc[df.eval(filter_t)]
    
    print(f'filter_t: {filter_t}')
    >>> filter_t: Test_Points == "3P3V" & Slew_1 == "5000"
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   John Zwinck    7 年前

    如果你能安装 numexpr ,我建议你试试 DataFrame.query() 为了这个。

    filter_str = 'Serial_Number == 2450 and Test_Points == "3P3V" and Voltage_1 == 11.6'
    df_filter = df.query(filter_str)
    

    如果你有 numexpr公司 安装,这可能是最快的解决方案。

    或者,构建一个掩码列表,然后合并它们。这与解决方案1类似,但比后者更好:

    masks = [df[x[0]] == x[1] for x in filter_l] # list of bool arrays
    filtered_df = df[np.logical_and.reduce(masks)] # combine and apply masks