如何优化这段代码?

时间:2018-08-23 08:10:22

标签: python python-3.x pandas

我的数据看起来像是字典列表:

  

wishlist_result [0] = {'userId':19814,'entityIds':[40、45、54、322]}

我将其转换为:

  

user_id:19814entity_id:40,   user_id:19814entity_id:45,   user_id:19814实体ID:54   user_id:19814实体ID:322

wishlist_data = pd.DataFrame()
for i in wishlist_result:
    wishlist_from_dict = pd.DataFrame.from_dict(
        wishlist_result[wishlist_result.index(i)])
    wishlist_data = wishlist_data.append(
        wishlist_from_dict, ignore_index=True)

wishlist_data = wishlist_data.rename(
    index=str, columns={
        "userId": "user_id",
        "entityIds": "entity_id"
    })

这段代码花费的时间太长,我有大约60k条记录,就像我上面提到的以任何方式在更短的时间内获得这种转换?

2 个答案:

答案 0 :(得分:1)

将数据框用于“一切”通常不是最佳解决方案。代码可能变得不可读,并且构造许多小的数据帧也可能非常慢。我的解决方案使用普通的Python容器解决您的问题:

import pandas as pd

wishlist_result = [
    {"userId": 19814, "entityIds": [40, 45, 54, 322]},
    {"userId": 19814, "entityIds": [12, 22]},
]

def flatten(data):
    flattened = []
    for entry in data:
        user_id = entry["userId"]
        entity_ids = entry["entityIds"]
        for entity_id in entity_ids:
            row = dict(user_id=user_id, entity_id=entity_id)
            flattened.append(row)

    return flattened


rows = flatten(wishlist_result)
df = pd.DataFrame(rows, columns=["user_id", "entity_id"])
print(df)

输出

   user_id  entity_id
0    19814         40
1    19814         45
2    19814         54
3    19814        322
4    19814         12
5    19814         22

我以长度为60000的列表作为您的方法的基准,该列表复制了您的wishlist_result示例。在旧Mac上,代码段的运行时间约为800毫秒。


如果您希望将其缩短,则嵌套列表理解也可以使用,运行时不会发生明显变化:

rows = [
    {"user_id": entry["userId"], "entity_id": entity_id}
    for entry in wishlist_result
    for entity_id in entry["entityIds"]
]

我经常避免使用嵌套的for循环进行列表解析,因为想要读取或重用我的代码的队友可能不知道执行顺序。但是这里涉及到的变量很清楚顺序。

答案 1 :(得分:0)

如果要串联很多帧,使用pd.concat比每次添加都要快:

all_wishlists = []
for i in wishlist_result:
    all_wishlists.append(
        pd.DataFrame.from_dict(wishlist_result[wishlist_result.index(i)])
    )

wishlist_data = pd.concat(all_wishlists, ignore_index=True)\
                  .rename(index=str,
                          columns={"userId": "user_id",
                                   "entityIds": "entity_id"})

更好的是,我们可以将其更改为列表理解,并将整个过程简化为:

wishlist_data = pd.concat([pd.DataFrame.from_dict(wishlist_result[wishlist_result.index(i)])
                           for i in wishlist_result], ignore_index=True)\
                  .rename(index=str,
                          columns={"userId": "user_id",
                                   "entityIds": "entity_id"})

您也不需要执行pd.DataFrame.from_dict(wishlist_result[wishlist_result.index(i)]) for i in wishlist_result-您不需要找到该项目然后再次为其编制索引。相反,您可以执行以下操作:

wishlist_data = pd.concat([pd.DataFrame.from_dict(result)
                           for result in wishlist_result], ignore_index=True)\
                  .rename(index=str,
                          columns={"userId": "user_id",
                                   "entityIds": "entity_id"})