gpt4 book ai didi

python - 使用列组合提高算术运算的性能

转载 作者:行者123 更新时间:2023-11-28 20:56:07 25 4
gpt4 key购买 nike

我有以下类型的数据框-
df

A   B   C
5 10 15
20 25 30

我要完成以下操作-

A_B   A_C  B_C
-0.33 -0.5 -0.2
-0.11 -0.2 -0.09

A_B,A_C,B_C对应-

A_B: A-B/A+B
A_C: A-C/A+C
B_C: B-C/B+C

我正在使用-

 colnames = df.columns.tolist()[:-1]
list_name=[]
for i,c in enumerate(colnames):
if i!=len(colnames):
for k in range(i+1,len(colnames)):
df[c+'_'+colnames[k]]=(df[c]-
df[colnames[k]])/(df[c]+df[colnames[k]])
list_name.append(c+'_'+colnames[k])

但问题是我的实际数据帧的大小为 5*381 形状,因此 A_B、A_C 等的实际组合数 正在出来是 5*72390 形状,需要 60 分钟才能运行。所以我试图将它转换成 numpy 数组,以便我可以使用 Numba 优化它以有效地计算它(Parallel programming approach to solve pandas problems),但我无法将它转换成 numpy 数组。此外,也欢迎任何其他解决此问题的解决方案。

最佳答案

使用:

df = pd.DataFrame({
'A':[5,20],
'B':[10,25],
'C':[15,30]
})

print (df)
A B C
0 5 10 15
1 20 25 30

首先将列的所有组合获取到 2 个列表(a 用于元组的第一个值,b 用于第二个):

from  itertools import combinations

a, b = zip(*(combinations(df.columns, 2)))

然后使用DataFrame.loc按列表重复列:

df1 = df.loc[:, a]
print (df1)
A A B
0 5 5 10
1 20 20 25

df2 = df.loc[:, b]
print (df2)
B C C
0 10 15 15
1 25 30 30

将值转换为最终 DataFrame 的 numpy 数组,并通过列表理解获取新的列名:

c = [f'{x}_{y}' for x, y in zip(a, b)]
arr1 = df1.values
arr2 = df2.values
df = pd.DataFrame((arr1-arr2)/(arr1+arr2), columns=c)
print (df)
A_B A_C B_C
0 -0.333333 -0.5 -0.200000
1 -0.111111 -0.2 -0.090909

另一个解决方案非常相似,只是通过arange 按列的长度创建组合,最后的新列名称通过索引创建:

from  itertools import combinations

a, b = zip(*(combinations(np.arange(len(df.columns)), 2)))
arr = df.values
cols = df.columns.values
arr1 = arr[:, a]
arr2 = arr[:, b]
c = [f'{x}_{y}' for x, y in zip(cols[np.array(a)], cols[np.array(b)])]
df = pd.DataFrame((arr1-arr2)/(arr1+arr2), columns=c)

性能:

在 5 行和 381 列中测试:

np.random.seed(2019)
df = pd.DataFrame(np.random.randint(10,100,(5,381)))
df.columns = ['c'+str(i+1) for i in range(df.shape[1])]
#print (df)

In [4]: %%timeit
...: a, b = zip(*(combinations(np.arange(len(df.columns)), 2)))
...: arr = df.values
...: cols = df.columns.values
...: arr1 = arr[:, a]
...: arr2 = arr[:, b]
...: c = [f'{x}_{y}' for x, y in zip(cols[np.array(a)], cols[np.array(b)])]
...: pd.DataFrame((arr1-arr2)/(arr1+arr2), columns=c)
...:
62 ms ± 7.29 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [5]: %%timeit
...: a, b = zip(*(combinations(df.columns, 2)))
...: df1 = df.loc[:, a]
...: df2 = df.loc[:, b]
...: arr1 = df1.values
...: arr2 = df2.values
...: c = [f'{x}_{y}' for x, y in zip(a, b)]
...: pd.DataFrame((arr1-arr2)/(arr1+arr2), columns=c)
...:
63.2 ms ± 253 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [7]: %%timeit
...: func1(df)
...:
89.2 ms ± 331 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [8]: %%timeit
...: a, b = zip(*(combinations(df.columns, 2)))
...: df1 = df.loc[:, a]
...: df2 = df.loc[:, b]
...: c = [f'{x}_{y}' for x, y in zip(a, b)]
...: pd.DataFrame((df1.values-df2.values)/(df1.values+df2.values), columns=c)
...:
69.8 ms ± 6.04 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

关于python - 使用列组合提高算术运算的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55116552/

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