假设我有两个Pandas数据帧,一个带负数,一个带正数,看起来像这样:
Columns 1 2 3 Columns 1 2 3
Rows Rows
1 -4 -6 -5 1 9 3 2
2 -2 -8 -4 2 6 4 5
3 -8 -8 -3 3 8 2 5
然后我有另一个具有相同尺寸的Pandas数据帧,但是具有负数和正数,如下所示:
Columns 1 2 3
Rows
1 -2 3 -4
2 -1 -2 2
3 6 -8 3
对于此混合数据帧中的每个元素,如果值为负,我想将其除以负数据帧中的相应元素,如果值为正,我想将其除以正数中的相应元素数据帧。结果如下:
Columns 1 2 3
Rows
1 0.5 1.0 0.8
2 0.5 0.25 0.4
3 0.75 1.0 0.6
执行此操作的最佳pythonic和/或有效方法是什么?我将拥有10,000个混合数据帧,包含50行和105列。
答案 0 :(得分:1)
我不了解效率,但您可以使用where
非常干净地完成这项工作:
>>> df1
0 1 2
0 3 8 7
1 9 9 3
2 1 1 9
>>> df2
0 1 2
0 -3 -7 -8
1 -4 -6 -3
2 -8 -8 -3
>>> df3
0 1 2
0 -10 7 1
1 -10 -4 9
2 7 -8 0
>>> df3/df1.where(df3 >= 0, df2)
0 1 2
0 3.333333 0.875000 0.142857
1 2.500000 0.666667 3.000000
2 7.000000 1.000000 0.000000
答案 1 :(得分:1)
这是一种替代方法,看起来更快。它基本上在混合数据帧上创建一个布尔掩码,然后将其除以适当的正或负数据帧。因为正面和负面是相互排斥的,所以可以将结果相加以产生分母。然后将其乘以混合数据帧以获得所需结果。
根据您的原始数据:
>>> df3 * (df3.gt(0) / df2 + df3.lt(0) / df1)
0 1 2
0 0.50 1.00 0.8
1 0.50 0.25 0.4
2 0.75 1.00 0.6
使用更大的10kx10k DataFrame:
df_pos = pd.DataFrame(np.random.randn(10000, 10000)).abs()
df_neg = -pd.DataFrame(np.random.randn(10000, 10000)).abs()
df_mixed = pd.DataFrame(np.random.randn(10000, 10000))
与@DSM解决方案的时间比较可以说更简单:
%timeit -n 10 df_mixed * (df_mixed.ge(0) / df_pos + df_mixed.lt(0) / df_neg)
10 loops, best of 3: 1.45 s per loop
%timeit -n 10 df_mixed / df_pos.where(df_mixed >= 0, df_neg)
10 loops, best of 3: 6.5 s per loop