【问题标题】:Faster Way to Iterate Through Rows of One DataFrame to Add columns to a Second DataFrame更快地遍历一个 DataFrame 的行以将列添加到第二个 DataFrame
【发布时间】:2021-05-11 19:12:37
【问题描述】:

我正在尝试找到一种更快的方法,将函数多次应用于 DataFrame 中的一组数据。

我有两个 DataFrame:

  1. Parameters:函数的每个参数都有一列,每一行是一个特定的参数集。还有一列为每个集合提供了一个唯一的名称。
  2. 原始数据:在一列中包含原始数据

对于每组参数,我想在原始DataFrame中添加一列,结果来自“func”,并将列名设置为参数集名称。

目前我正在遍历参数DataFrame的行,但我觉得有更好的方法。

我正在尝试查看是否有矢量化解决方案,但到目前为止,我使用两个 DataFrame 都没有成功。

我已经尝试在这篇文章中遵循 cs95 的答案,但几乎所有矢量化或列表推导的示例都只处理单个 DataFrame: How to iterate over rows in a DataFrame in Pandas

有没有更好的方法来做到这一点?

我觉得我可能缺少一些明显的东西。

import pandas as pd

def func(data, a, b, c):
    return data["original"] + a + b * c


parameters = pd.DataFrame(
    {
        "name": ["set_1", "set_2", "set_3"],
        "a": [1, 2, 3],
        "b": [4, 5, 6],
        "c": [7, 8, 9],
    }
)

data = pd.DataFrame({"original": [10, 11, 12, 13, 14, 15]})

for i, row in parameters.iterrows():
    data[row["name"]] = func(data, row["a"], row["b"], row["c"])

    Inputs:
    
Parameters DataFrame:
    name  a  b  c
0  set_1  1  4  7
1  set_2  2  5  8
2  set_3  3  6  9
    
Original Data DataFrame:
       original
    0        10
    1        11
    2        12
    3        13
    4        14
    5        15
    

    Output:
    
       original  set_1  set_2  set_3
    0        10     39     52     67
    2        12     41     54     69
    3        13     42     55     70
    4        14     43     56     71
    5        15     44     57     72

【问题讨论】:

    标签: python pandas dataframe iteration vectorization


    【解决方案1】:

    不直接使用循环(暗示在apply()

    • 使用笛卡尔积将数据合并在一起
    • apply()进行计算
    • 使用pivot() 重塑您想要的输出结构
    df = pd.read_csv(io.StringIO("""       original
        0        10
        1        11
        2        12
        3        13
        4        14
        5        15"""), sep="\s+")
    
    dfp = pd.read_csv(io.StringIO("""    name  a  b  c
    0  set_1  1  4  7
    1  set_2  2  5  8
    2  set_3  3  6  9"""), sep="\s+")
    
    # catesian product data with params
    dfm = df.assign(foo=1).merge(dfp.assign(foo=1), on="foo")
    # do the calc
    dfm = dfm.assign(calc=dfm.apply(lambda x: x.original + x.a + x.b * x.c, axis=1))
    # reshape
    dfm = dfm.pivot(index="original", columns="name", values="calc").reset_index()
    
    original set_1 set_2 set_3
    0 10 39 52 67
    1 11 40 53 68
    2 12 41 54 69
    3 13 42 55 70
    4 14 43 56 71
    5 15 44 57 72

    【讨论】:

      【解决方案2】:

      您可以修改下面的代码以满足您的期望,我将第 1 行(原始 = 11)留在那里;应该很容易修改。

      下面的代码避免了迭代,因为它可能很慢。它的作用是先从参数中获取值,然后对每一列与 data['original'] 相乘以获得最终输出:

      def func(left_df, right_df):
          right_df = right_df.copy()
          new_headers = right_df["name"].array
          right_df = (right_df["a"] + right_df["b"] * right_df["c"]).array
          right_df = dict(zip(new_headers, new))
          return left_df.assign(
              **{key: left_df["original"] + value for key, value in right_df.items()}
          )
      
      
      data.pipe(func, parameters)
      
      
          original    set_1   set_2   set_3
      0        10       39      52    67
      1        11       40      53    68
      2        12       41      54    69
      3        13       42      55    70
      4        14       43      56    71
      5        15       44      57    72
      

      【讨论】:

        【解决方案3】:

        如下定义你的函数:

        def func2(dataCol, a, b, c):
            return dataCol[:, np.newaxis] + a[np.newaxis, :] + b[np.newaxis, :] * c[np.newaxis, :]
        

        区别:

        • 第一个参数是一个源数据列,不是整个DataFrame,
        • 剩下的3个参数也是columns(取自parameters), 而不是单个值。

        然后,要获得结果,请按以下方式调用它:

        data[parameters.name.tolist()] = func2(data.original, parameters.a,
            parameters.b, parameters.c)
        

        使用 %timeit 我检查了您和我的代码的执行时间。 我的代码的执行时间大约占您代码的 60%。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-05-27
          • 2022-11-21
          • 1970-01-01
          • 1970-01-01
          • 2019-03-10
          • 1970-01-01
          • 2018-08-26
          相关资源
          最近更新 更多