Python - 遍历数据框并创建 class 个对象
Python - Loop though dataframe and create class objects
我有以下数据框(已经处理和清理以删除特殊字符等)。
parent_id
members_id
item_id
item_name
par_100
member1
item1
t shirt
par_100
member1
item2
denims
par_102
member2
item3
shirt
par_103
member3
item4
shorts
par_103
member3
item5
blouse
par_103
member4
item6
sweater
par_103
member4
item7
hoodie
和以下 class 结构
class Member:
def __init__(self, id):
self.member_id = id
self.items = []
class Item:
def __init__(self, id, name):
self.item_id = id
self.name = name
数据框中的行数约为 500K+。我想创建一个字典(或其他结构),其中“parent_id”是主键,列映射到 class 对象。创建指定的数据结构后。我将根据一些业务逻辑执行一些操作,我将不得不遍历所有成员。
第一步是从数据帧创建数据结构。我有以下代码可以完成这项工作,但处理所有 500k+ 行需要大约 3 个小时。
# sorted_data is the dataframe mentioned above
parent_key_list = sorted_data['parent_id'].unique().tolist()
for index, parent_key in enumerate(parent_key_list):
temp_data = sorted_data.loc[sorted_data['parent_id'] == parent_key]
unique_members = temp_data["members_id"].unique()
for us in unique_members:
items = temp_data.loc[temp_data['members_id'] == us]
temp_member = Member(items[0]["members_id"])
for index, row in items.iterrows():
temp_member.items.append(Item(row["item_id"], row["item_name"]))
parent_dict[parent_key].append(temp_member)
由于 .loc
是非常耗时的操作,我尝试用 numpy 数组做同样的事情,但性能要差得多。有没有更好的方法来减少处理时间?
您可以使用 iterrows 或 itertuples 来迭代数据框并初始化您的实例。为了让它更容易一点(如果你坚持class,我个人会为成员和项目使用字典),我会做以下事情:
- 将会员 ID 属性 添加到项目
- 迭代数据框并仅初始化项目实例
- 之后,您可以检查所有项目实例,以便识别唯一成员及其项目
试试这个:
from collections import defaultdict
parent_dict = defaultdict(lambda: [])
for (parent_id, members_id), sdf in sorted_data.groupby(['parent_id', 'members_id']):
member = Member(members_id)
items = sdf.apply(lambda r: Item(r.item_id, r.item_name), axis=1).to_list()
member.items.extend(items)
parent_dict[parent_id].append(member)
它利用.groupby
函数为每个成员划分数据集。然后,您可以在 .groupby
生成的子数据帧上使用 .apply
创建项目对象,并将其转换为列表 if Item
对象,然后您可以使用它来更新每个成员 items
属性。结果成员存储在 defaultdict
中,您可以使用 dict()
将其转换回普通成员(尽管它们的工作方式完全相同)。
我有以下数据框(已经处理和清理以删除特殊字符等)。
parent_id | members_id | item_id | item_name |
---|---|---|---|
par_100 | member1 | item1 | t shirt |
par_100 | member1 | item2 | denims |
par_102 | member2 | item3 | shirt |
par_103 | member3 | item4 | shorts |
par_103 | member3 | item5 | blouse |
par_103 | member4 | item6 | sweater |
par_103 | member4 | item7 | hoodie |
和以下 class 结构
class Member:
def __init__(self, id):
self.member_id = id
self.items = []
class Item:
def __init__(self, id, name):
self.item_id = id
self.name = name
数据框中的行数约为 500K+。我想创建一个字典(或其他结构),其中“parent_id”是主键,列映射到 class 对象。创建指定的数据结构后。我将根据一些业务逻辑执行一些操作,我将不得不遍历所有成员。
第一步是从数据帧创建数据结构。我有以下代码可以完成这项工作,但处理所有 500k+ 行需要大约 3 个小时。
# sorted_data is the dataframe mentioned above
parent_key_list = sorted_data['parent_id'].unique().tolist()
for index, parent_key in enumerate(parent_key_list):
temp_data = sorted_data.loc[sorted_data['parent_id'] == parent_key]
unique_members = temp_data["members_id"].unique()
for us in unique_members:
items = temp_data.loc[temp_data['members_id'] == us]
temp_member = Member(items[0]["members_id"])
for index, row in items.iterrows():
temp_member.items.append(Item(row["item_id"], row["item_name"]))
parent_dict[parent_key].append(temp_member)
由于 .loc
是非常耗时的操作,我尝试用 numpy 数组做同样的事情,但性能要差得多。有没有更好的方法来减少处理时间?
您可以使用 iterrows 或 itertuples 来迭代数据框并初始化您的实例。为了让它更容易一点(如果你坚持class,我个人会为成员和项目使用字典),我会做以下事情:
- 将会员 ID 属性 添加到项目
- 迭代数据框并仅初始化项目实例
- 之后,您可以检查所有项目实例,以便识别唯一成员及其项目
试试这个:
from collections import defaultdict
parent_dict = defaultdict(lambda: [])
for (parent_id, members_id), sdf in sorted_data.groupby(['parent_id', 'members_id']):
member = Member(members_id)
items = sdf.apply(lambda r: Item(r.item_id, r.item_name), axis=1).to_list()
member.items.extend(items)
parent_dict[parent_id].append(member)
它利用.groupby
函数为每个成员划分数据集。然后,您可以在 .groupby
生成的子数据帧上使用 .apply
创建项目对象,并将其转换为列表 if Item
对象,然后您可以使用它来更新每个成员 items
属性。结果成员存储在 defaultdict
中,您可以使用 dict()
将其转换回普通成员(尽管它们的工作方式完全相同)。