提高计算匹配熊猫特定条件的随机样本的性能

乔治·海勒

对于某些数据集,group_1我需要迭代所有行k时间以获得稳健性,并group_2根据表示为数据框列的某些标准找到另一个数据框的匹配随机样本不幸的是,这相当缓慢。如何提高性能?

瓶颈是apply-ed 函数,即randomMatchingCondition

import tqdm                                                                                                   
import numpy as np
import pandas as pd
from tqdm import tqdm
tqdm.pandas()

seed = 47
np.random.seed(seed)

###################################################################
# generate dummy data
size = 10000
df = pd.DataFrame({i: np.random.randint(1,100,size=size) for i in ['metric']})
df['label'] =  np.random.randint(0,2, size=size)
df['group_1'] =  pd.Series(np.random.randint(1,12, size=size)).astype(object)
df['group_2'] =  pd.Series(np.random.randint(1,10, size=size)).astype(object)

group_0 = df[df['label'] == 0]
group_0 = group_0.reset_index(drop=True)
group_0 = group_0.rename(index=str, columns={"metric": "metric_group_0"})

join_columns_enrich = ['group_1', 'group_2']
join_real = ['metric_group_0']
join_real.extend(join_columns_enrich)
group_0 = group_0[join_real]
display(group_0.head())
group_1 = df[df['label'] == 1]
group_1 = group_1.reset_index(drop=True)
display(group_1.head())

###################################################################
# naive find random element matching condition
def randomMatchingCondition(original_element, group_0, join_columns, random_state):
    limits_dict = original_element[join_columns_enrich].to_dict()
    query = ' & '.join([f"{k} == {v}" for k, v in limits_dict.items()])
    candidates = group_0.query(query)
    if len(candidates) > 0:
        return candidates.sample(n=1, random_state=random_state)['metric_group_0'].values[0]
    else:
        return np.nan
###################################################################
# iterate over pandas dataframe k times for more robust sampling
k = 3
resulting_df = None
for i in range(1, k+1):
    group_1['metric_group_0'] = group_1.progress_apply(randomMatchingCondition,
                                                                  args=[group_0, join_columns_enrich, None],
                                                                  axis = 1)
    group_1['run'] = i
    if resulting_df is None:
        resulting_df = group_1.copy()
    else:
        resulting_df = pd.concat([resulting_df, group_1])
resulting_df.head()

尝试对数据进行预排序:

group_0 = group_0.sort_values(join_columns_enrich)
group_1 = group_1.sort_values(join_columns_enrich)

没有任何区别。

乔治·海勒

@smiandras,你是对的。摆脱 for 循环很重要。

变体 1:多个样本:

def randomMatchingCondition(original_element, group_0, join_columns, k, random_state):
    limits_dict = original_element[join_columns_enrich].to_dict()
    query = ' & '.join([f"{k} == {v}" for k, v in limits_dict.items()])
    candidates = group_0.query(query)
    if len(candidates) > 0:
        return candidates.sample(n=k, random_state=random_state, replace=True)['metric_group_0'].values
    else:
        return np.nan
###################################################################
# iterate over pandas dataframe k times for more robust sampling
k = 3
resulting_df = None

#######################
# trying to improve performance: sort both dataframes
group_0 = group_0.sort_values(join_columns_enrich)
group_1 = group_1.sort_values(join_columns_enrich)
#######################

group_1['metric_group_0'] = group_1.progress_apply(randomMatchingCondition,
                                                   args=[group_0, join_columns_enrich, k, None],
                                                   axis = 1)
print(group_1.isnull().sum())
group_1 = group_1[~group_1.metric_group_0.isnull()]
display(group_1.head())

s=pd.DataFrame({'metric_group_0':np.concatenate(group_1.metric_group_0.values)},index=group_1.index.repeat(group_1.metric_group_0.str.len()))
s = s.join(group_1.drop('metric_group_0',1),how='left')
s['pos_in_array'] = s.groupby(s.index).cumcount()
s.head()

变体 2:通过本机 JOIN 操作优化的所有可能样本。

警告这有点不安全,因为它可能会生成大量的行:

size = 1000
df = pd.DataFrame({i: np.random.randint(1,100,size=size) for i in ['metric']})
df['label'] =  np.random.randint(0,2, size=size)
df['group_1'] =  pd.Series(np.random.randint(1,12, size=size)).astype(object)
df['group_2'] =  pd.Series(np.random.randint(1,10, size=size)).astype(object)

group_0 = df[df['label'] == 0]
group_0 = group_0.reset_index(drop=True)
join_columns_enrich = ['group_1', 'group_2']
join_real = ['metric']
join_real.extend(join_columns_enrich)
group_0 = group_0[join_real]
display(group_0.head())
group_1 = df[df['label'] == 1]
group_1 = group_1.reset_index(drop=True)
display(group_1.head())
df = group_1.merge(group_0, on=join_columns_enrich)
display(df.head())
print(group_1.shape)
df.shape

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

熊猫创建随机样本而不重复

来自分类Dev

特定列条目的比率1:1的熊猫随机样本

来自分类Dev

熊猫中数据框的子集的随机样本

来自分类Dev

熊猫:创建随机样本和相关矩阵

来自分类Dev

两个数组的Python随机样本,但索引匹配

来自分类Dev

计算符合特定条件的熊猫组中的行

来自分类Dev

在满足特定条件的熊猫行之间进行简单的计算

来自分类Dev

R:随机样本与1个随机样本的分布

来自分类Dev

生成相关的随机样本

来自分类Dev

如何模拟50个随机样本并计算每个样本的均值和方差

来自分类Dev

随机样本中的“样本大于总体”

来自分类Dev

具有“每个条件至少一个”条件的行的随机样本

来自分类Dev

R-在循环中使用“哪个”条件提取条件随机样本

来自分类Dev

如何在多索引熊猫数据框中获取随机样本?

来自分类Dev

从熊猫数据框中获取随机样本,但每个值仅获取一个

来自分类Dev

熊猫根据特定条件选择数据

来自分类Dev

熊猫根据特定条件选择数据

来自分类Dev

按年份分组和其他列,并根据特定条件的熊猫计算平均值

来自分类Dev

提取带有嵌套条件的data.frame中的行的随机样本

来自分类Dev

如何提取具有随组而异的多个条件的随机样本?

来自分类Dev

带组的SQL随机样本

来自分类Dev

从数据集中获取加权随机样本

来自分类Dev

python:具有概率的随机样本

来自分类Dev

来自ArrayType Pyspark列的随机样本

来自分类Dev

来自对数正态分布的随机样本

来自分类Dev

从数据集中获取加权随机样本

来自分类Dev

mongodb随机样本奇怪的行为

来自分类Dev

从 URL 中读取随机样本

来自分类Dev

如何生成R中具有特定分割比的大小为80的随机样本?

Related 相关文章

热门标签

归档