【发布时间】:2022-01-18 02:24:34
【问题描述】:
假设我有两个 pandas 数据框(df_a 和 df_b),其中每一行代表一个玩具和该玩具的特征。一些伪装功能:
- 已售出(是/否)
- 颜色
- Size_Group
- 形状
- 生产日期
假设 df_a 相对较小(几千行的 10s)而 df_b 相对较大(>100 万行)。
然后对于 df_a 中的每一行,我想:
- 从 df_b 中找到所有与 df_a 中相同类型的玩具(例如相同的颜色组)
- df_b 玩具也必须在给定的 df_a 玩具之前制作
- 然后找到已售出的比率(因此计算已售出/计算所有匹配)
进行上述每行计算的最有效方法是什么?
到目前为止,我想出的最好的方法如下所示。 (注意代码可能有一两个错误,因为我是从不同的用例粗略输入的)
cols = ['Color', 'Size_Group', 'Shape']
# Run this calculation for multiple features
for col in cols:
print(col + ' - Started')
# Empty list to build up the calculation in
ratio_list = []
# Start the iteration
for row in df_a.itertuples(index=False):
# Relevant values from df_a
relevant_val = getattr(row, col)
created_date = row.Date_Made
# df to keep the overall prior toy matches
prior_toys = df_b[(df_b.Date_Made < created_date) & (df_b[col] == relevant_val)]
prior_count = len(prior_toys)
# Now find the ones that were sold
prior_sold_count = len(prior_toys[prior_toys.Was_Sold == "Y"])
# Now make the calculation and append to the list
if prior_count == 0:
ratio = 0
else:
ratio = prior_sold_count / prior_count
ratio_list.append(ratio)
# Store the calculation in the original df_a
df_a[col + '_Prior_Sold_Ratio'] = ratio_list
print(col + ' - Finished')
使用.itertuples() 很有用,但这仍然很慢。有没有更有效的方法或我缺少的东西?
编辑 添加了以下脚本,它将模拟上述场景的数据:
import numpy as np
import pandas as pd
colors = ['red', 'green', 'yellow', 'blue']
sizes = ['small', 'medium', 'large']
shapes = ['round', 'square', 'triangle', 'rectangle']
sold = ['Y', 'N']
size_df_a = 200
size_df_b = 2000
date_start = pd.to_datetime('2015-01-01')
date_end = pd.to_datetime('2021-01-01')
def random_dates(start, end, n=10):
start_u = start.value//10**9
end_u = end.value//10**9
return pd.to_datetime(np.random.randint(start_u, end_u, n), unit='s')
df_a = pd.DataFrame(
{
'Color': np.random.choice(colors, size_df_a),
'Size_Group': np.random.choice(sizes, size_df_a),
'Shape': np.random.choice(shapes, size_df_a),
'Was_Sold': np.random.choice(sold, size_df_a),
'Date_Made': random_dates(date_start, date_end, n=size_df_a)
}
)
df_b = pd.DataFrame(
{
'Color': np.random.choice(colors, size_df_b),
'Size_Group': np.random.choice(sizes, size_df_b),
'Shape': np.random.choice(shapes, size_df_b),
'Was_Sold': np.random.choice(sold, size_df_b),
'Date_Made': random_dates(date_start, date_end, n=size_df_b)
}
)
【问题讨论】:
-
@Ugurcan 我知道这是最理想的情况,但我不知道如何向量化上述逻辑。
-
这很难为您提供帮助,因为我们没有数据框示例,也没有列类型,并且提供的示例并不完全完整。拥有一个最小的 reproducible working 示例应该对我们有很大帮助(最后是你)。
Some other conditions left out for simplicity是个问题,因为隐藏条件可能不适用于未来提供的答案 -
@JérômeRichard 我将编辑掉“其他条件”位。我的观点是强调我可能需要添加更多条件,但我们可以认为这并不重要。至于列类型,我认为它是从提供的示例名称(字符串和日期)中暗示的。我无法提供真实数据(而且它要复杂得多),但我会看看我是否可以提供一个脚本来生成模拟玩具数据。
标签: pandas dataframe performance loops