【发布时间】:2020-05-08 00:14:08
【问题描述】:
我有两个具有相同列的数据框:
数据框 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 的此类问题?或者我除了并行化迭代别无选择?
编辑:
随着数据框大小的增加第二个选项会产生更好的运行时间,但仍然需要几秒钟才能完成。
提前致谢
【问题讨论】:
-
您的问题表述得很好,唯一缺少的是带有
pd.DataFrame的两个数据框,因此我们可以立即运行代码并获得与您相同的结果。现在您的列已被截断,因此问题无法重现。 -
您可能想要类似:
df1.corrwith(df2, axis = 1)但数据会有所帮助 -
感谢您的关注!源是包含技术信息的巨大 CSV。我编辑了问题以添加可重现的示例
-
选项 2 中哪个部分较慢:
df_crossjoin或compute_pearson? -
我不太确定。也许做一个交叉连接,然后像
apply这样的线性操作会使事情(自然地)比只计算整个数据集慢一次。由于 Pandas 不并行化,因此循环实现是一种可行的替代方案
标签: python python-3.x pandas