gpt4 book ai didi

python - 优化两个 Pandas Dataframe 之间的笛卡尔积

转载 作者:行者123 更新时间:2023-12-03 14:23:41 27 4
gpt4 key购买 nike

我有两个具有相同列的数据框:

数据框 1 :

          attr_1  attr_77 ... attr_8
userID
John 1.2501 2.4196 ... 1.7610
Charles 0.0000 1.0618 ... 1.4813
Genarito 2.7037 4.6707 ... 5.3583
Mark 9.2775 6.7638 ... 6.0071

数据框 2 :
          attr_1  attr_77 ... attr_8
petID
Firulais 1.2501 2.4196 ... 1.7610
Connie 0.0000 1.0618 ... 1.4813
PopCorn 2.7037 4.6707 ... 5.3583

我想生成所有可能组合的相关性和 p 值数据框,结果如下:
   userId   petID      Correlation    p-value
0 John Firulais 0.091447 1.222927e-02
1 John Connie 0.101687 5.313359e-03
2 John PopCorn 0.178965 8.103919e-07
3 Charles Firulais -0.078460 3.167896e-02

问题是笛卡尔积生成了超过 300 万个元组。花几分钟完成 .这是我的代码,我写了两种选择:

首先, 初始数据帧 :
df1 = pd.DataFrame({
'userID': ['John', 'Charles', 'Genarito', 'Mark'],
'attr_1': [1.2501, 0.0, 2.7037, 9.2775],
'attr_77': [2.4196, 1.0618, 4.6707, 6.7638],
'attr_8': [1.7610, 1.4813, 5.3583, 6.0071]
}).set_index('userID')

df2 = pd.DataFrame({
'petID': ['Firulais', 'Connie', 'PopCorn'],
'attr_1': [1.2501, 0.0, 2.7037],
'attr_77': [2.4196, 1.0618, 4.6707],
'attr_8': [1.7610, 1.4813, 5.3583]
}).set_index('petID')

选项 1 :
# Pre-allocate space
df1_keys = df1.index
res_row_count = len(df1_keys) * df2.values.shape[0]
genes = np.empty(res_row_count, dtype='object')
mature_mirnas = np.empty(res_row_count, dtype='object')
coff = np.empty(res_row_count)
p_value = np.empty(res_row_count)

i = 0
for df1_key in df1_keys:
df1_values = df1.loc[df1_key, :].values
for df2_key in df2.index:
df2_values = df2.loc[df2_key, :]
pearson_res = pearsonr(df1_values, df2_values)

users[i] = df1_key
pets[i] = df2_key
coff[i] = pearson_res[0]
p_value[i] = pearson_res[1]
i += 1

# After loop, creates the resulting Dataframe
return pd.DataFrame(data={
'userID': users,
'petID': pets,
'Correlation': coff,
'p-value': p_value
})

选项 2(较慢) ,来自 here :
# Makes a merge between all the tuples
def df_crossjoin(df1_file_path, df2_file_path):
df1, df2 = prepare_df(df1_file_path, df2_file_path)

df1['_tmpkey'] = 1
df2['_tmpkey'] = 1

res = pd.merge(df1, df2, on='_tmpkey').drop('_tmpkey', axis=1)
res.index = pd.MultiIndex.from_product((df1.index, df2.index))

df1.drop('_tmpkey', axis=1, inplace=True)
df2.drop('_tmpkey', axis=1, inplace=True)

return res

# Computes Pearson Coefficient for all the tuples
def compute_pearson(row):
values = np.split(row.values, 2)
return pearsonr(values[0], values[1])

result = df_crossjoin(mrna_file, mirna_file).apply(compute_pearson, axis=1)

有没有更快的方法用 Pandas 解决这样的问题?或者我除了并行化迭代别无选择?

编辑:

随着数据帧大小的增加 第二个选项导致更好的运行时间 ,但它仍然需要几秒钟才能完成。

提前致谢

最佳答案

在测试的所有替代方案中,给我最好结果的一个如下:

  • 一个迭代产品是用
    itertools.product() .
  • 两个 iterrows 上的所有迭代都在一个 Pool 上执行
    并行进程(使用 map 函数)。

  • 为了提高性能,函数 compute_row_cython是用 Cython 编译的正如 this section 中所建议的那样 Pandas 文档的:

    cython_modules.pyx文件:
    from scipy.stats import pearsonr
    import numpy as np

    def compute_row_cython(row):
    (df1_key, df1_values), (df2_key, df2_values) = row
    cdef (double, double) pearsonr_res = pearsonr(df1_values.values, df2_values.values)
    return df1_key, df2_key, pearsonr_res[0], pearsonr_res[1]

    然后我设置了 setup.py :
    from distutils.core import setup
    from Cython.Build import cythonize

    setup(name='Compiled Pearson',
    ext_modules=cythonize("cython_modules.pyx")

    最后我编译它: python setup.py build_ext --inplace
    最终代码 被留下了,然后:
    import itertools
    import multiprocessing
    from cython_modules import compute_row_cython

    NUM_CORES = multiprocessing.cpu_count() - 1

    pool = multiprocessing.Pool(NUM_CORES)
    # Calls to Cython function defined in cython_modules.pyx
    res = zip(*pool.map(compute_row_cython, itertools.product(df1.iterrows(), df2.iterrows()))
    pool.close()
    end_values = list(res)
    pool.join()

    既不是 Dask,也不是 merge功能与 apply使用给了我更好的结果。甚至没有使用 Cython 优化应用程序。事实上,这两种方法的替代方案给了我内存错误,当使用 Dask 实现解决方案时,我不得不生成多个分区,这降低了性能,因为它必须执行许多 I/O 操作。

    Dask 的解决方案可以在我的 other question 中找到.

    关于python - 优化两个 Pandas Dataframe 之间的笛卡尔积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59849498/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com