【问题标题】:Step through pandas dataframe based on keyword根据关键字单步执行 pandas 数据框
【发布时间】:2017-08-16 19:26:37
【问题描述】:

我有一个 pandas 数据框,看起来像

In [97]: df
Out[97]:
      A1  A1_step  A1_step_n  LB7  dF
0  40000      500          2    4   2
1  60000      300          3    6   7

我想使用具有stepstep_n 关键字的列以指定的步长“步进”(迭代)数据框的行。因此,在上面的示例数据框中,我想以 500 的步长对 40000 行的 A1 列进行两次迭代,对于 60000 的行,以 300 的步长迭代三次。最终,我希望数据框看起来像

In [98]: df2
Out[98]:
      A1    LB7  dF
0  40000      4   2
1  40500      4   2
2  60000      6   7
3  60300      6   7
4  60600      6   7

LB7dF 的值被传递,不再需要“步骤”列。

我尝试循环遍历列,试图找出哪些列被迭代并循环遍历这些循环以添加到数据框,但它很快就会变得非常混乱,我希望这里有人可以引导我更好的路径。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    我想分享我最终选择的答案,因为它证明了我正在寻找的一般性水平。

    import pandas as pd
    from itertools import product
    
    dfs = []
    step_cols = [col[:-7] for col in df.columns if '_step_n' in col]
    const_cols = ([col + '_step' for col in step_cols] + step_cols +
                  [col + '_step_n' for col in step_cols])
    
    for i, row in df.iterrows():
        ranges = []
        for col in step_cols:
            start = row[col]
            stop = row[col] + row[col + '_step'] * row[col + '_step_n']
            step = row[col + '_step']
            ranges.append(list(range(start, stop, step)))
        combos = list(product(*ranges))
        dfs.append(pd.DataFrame(
            {**{k: v for k, v in zip(step_cols, zip(*combos))},
             **df.drop(const_cols, axis=1).iloc[i].to_dict()}))
    
    df2 = pd.concat(dfs, ignore_index=True)
    

    所以如果原来的df

    In [226]: df
    Out[226]:
          A1  LB7  dF  A1_step_n  A1_step
    0  40000    4   2          2      500
    1  60000    6   7          3      300
    

    生成的df2

    In [227]: df2
    Out[227]:
          A1  LB7  dF
    0  40000    4   2
    1  40500    4   2
    2  60000    6   7
    3  60300    6   7
    4  60600    6   7
    

    这还有一个额外的好处,那就是将“_step”和“_step_n”附加到其他列名称允许您遍历笛卡尔积。例如。如果原来的df

    In [230]: df
    Out[230]:
        A1  LB7  dF  A1_step_n  A1_step  dF_step_n  dF_step
    0  100    5  15          4       50          2        7
    1  200    8  30          3       30          3        4
    

    生成的df2 将遍历A1dF

    In [231]: df2
    Out[231]:
         A1  LB7  dF
    0   100    5  15
    1   100    5  22
    2   150    5  15
    3   150    5  22
    4   200    5  15
    5   200    5  22
    6   250    5  15
    7   250    5  22
    8   200    8  30
    9   200    8  34
    10  200    8  38
    11  230    8  30
    12  230    8  34
    13  230    8  38
    14  260    8  30
    15  260    8  34
    16  260    8  38
    

    【讨论】:

      【解决方案2】:
      v = df.values
      reps = np.arange(len(v)).repeat(v[:, 2])
      a1 = np.concatenate([np.arange(a, a + b * c, b) for a, b, c in v[:, :3]])[:, None]
      v1 = v[:, 3:][reps]
      pd.DataFrame(np.hstack([a1, v1]), columns=['A1', 'LB7', 'dF'])
      
      
            A1  LB7  dF
      0  40000    4   2
      1  40500    4   2
      2  60000    6   7
      3  60300    6   7
      4  60600    6   7
      

      【讨论】:

        【解决方案3】:

        您可以像这样遍历行并手动构建您的数据框:

        dfs = []
        col_step = df.columns.str.extract('(.*\_step$)', expand=False).dropna()[0]
        col_step_n = df.columns.str.extract('(.*\_step\_n$)', expand=False).dropna()[0]
        
        for i, row in df.iterrows():
            start = row['A1']
            steps = row[col_step_n]
            size = row[col_step]
            stop = start + size * (steps)
            df_cur = pd.DataFrame({'A1': np.arange(start, stop, size), 'LB7':row['LB7'], 'dF':row['dF']})
            dfs.append(df_cur)
        
        df_final = pd.concat(dfs, ignore_index=True)
        

        输出

        print(df_final)
              A1  LB7  dF
        0  40000    4   2
        1  40500    4   2
        2  60000    6   7
        3  60300    6   7
        4  60600    6   7
        

        【讨论】:

        • 谢谢,这很有帮助。我应该补充一点,虽然我不知道先验的列名,只是有一些在名称后面附加了“_step”和“_step_n”。也就是说,我想我应该能够从这里拿走它。我会暂时保留这个问题,以防其他人(或你自己)给出一个解决方案,包括首先找出哪些列有“_step”和“_step_n”。
        • 您应该能够使用正则表达式来提取列字符串名称。上述修复应该有效。
        猜你喜欢
        • 2022-01-02
        • 1970-01-01
        • 2016-11-17
        • 2017-10-22
        • 2016-06-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-10
        相关资源
        最近更新 更多