【问题标题】:Pandas iterrows too slow, how can I vectorize this code?Pandas iterrows 太慢了,我该如何向量化这段代码?
【发布时间】:2021-10-26 14:13:00
【问题描述】:

我是一名初级数据科学家,我正在尝试解决一个对于有经验的程序员来说可能很简单的问题。我正在处理 GCP 上的大数据,我需要优化我的代码。

                                      [...]
    def send_to_bq(self, df):
        result = []
        for i, row in df[["id", "vectors", "processing_timestamp"]].iterrows():
            data_dict = {
                "processing_timestamp": str(row["processing_timestamp"]),
                "id": row["id"],
                "embeddings_vector": [str(x) for x in row["vectors"]],
            }
            result.append(data_dict)
                                      [...]

我们的 DataFrame 具有以下模式:

           id                                               name  \
0  3498001704  roupa natal flanela animais estimacao traje ma...   

                                             vectors  \
0  [0.4021441, 0.45425776, 0.3963987, 0.23765437,...   

        processing_timestamp  
0 2021-10-26 23:48:57.315275

在 DataFrame 上使用 iterrows 太慢了。我一直在研究替代方案,我知道:

  1. 我可以使用申请
  2. 我可以通过 Pandas 系列对其进行矢量化(优于应用)
  3. 我可以通过 Numpy 对其进行向量化(比 Pandas 向量化更好)
  4. 我可以使用 Swifter - 它使用 apply 方法,然后在 Dask、Ray 和矢量化之间为您决定更好的解决方案

但我不知道如何为这些解决方案转换我的代码。

谁能帮我演示我的代码的解决方案?一个就足够了,但如果有人能展示不止一个解决方案,这对这件事来说真的很有教育意义。

任何帮助我都会感激不尽!

【问题讨论】:

  • 请使用print(df.head().to_string(index=False)) 的输出更新您的帖子作为可重复的示例
  • 使用df.to_dict(['processing_timestamp', 'id', 'embeddings_vector'])
  • 感谢您的修改。最佳实践是让我的代码在 Stack Overflow 上可重现,你是对的。我将打印头部并编辑我的问题。
  • 我已经编辑了我的问题并合并了 DataFrame 中的头部。

标签: python pandas dataframe numpy swifter


【解决方案1】:

你可以使用agg:

>>> df.agg({'id': str, 'vectors': lambda v: [str(i) for i in v], 
            'processing_timestamp': str}).to_dict('records')

[{'id': '3498001704',
  'vectors': ['0.4021441', '0.45425776', '0.3963987', '0.23765437'],
  'processing_timestamp': '2021-10-26 23:48:57.315275'}]

【讨论】:

    【解决方案2】:

    因此,您基本上将所有内容都转换为字符串,然后将 DataFrame 转换为 dict 列表

    对于第二部分,有一个pandas方法to_dict。对于第一部分,我将使用astypeapply 仅用于转换类型

    df["processing_timestamp"] = df["processing_timestamp"].astype(str)
    df["embeddings_vector"] = df["vectors"].apply(lambda row: [str(x) for x in row])
    result = df[["id", "embeddings_vector", "processing_timestamp"]].to_dict('records')
    

    在没有样本数据的情况下有点难以测试,但希望这会有所帮助;)另外,就像我对 lambda 函数所做的那样,您基本上可以将整个循环体包裹在 apply 中,但这会产生很多临时性字典要快。

    【讨论】:

    • 效果很好。尽管我没有发布数据样本,但您理解正确(我需要先将其匿名化)。我需要将所有内容都转换为字符串,这是更好的解决方案,使用 astype 作为时间戳,使用 lambda 函数作为向量列表(实际上是一个数组)并将 to_dict 与“记录”一起使用,这样它就可以类似于 iterrows 进行迭代。跨度>
    【解决方案3】:

    您可以使用pandas.DataFrame 方法将其转换为其他类型,例如DataFrame.to_dict()more

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-02
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      • 2019-07-16
      • 2019-12-21
      • 2015-06-04
      相关资源
      最近更新 更多