反转行顺序和操作效率

时间:2019-04-08 07:08:58

标签: python pandas

我知道要反转我可以使用的熊猫数据框中的行顺序

df = df.iloc[::-1]

但是我的问题是要对其进行更多操作。例如,

def transform (x) :
    x = x.iloc[::-1]
    x['a'] = x['a'] * 2
    return x

对于

x = pd.DataFrame({'a' : np.arange(5), 'b' : np.arange(5)})

是非常慢的-时间基准测试在我的计算机上给出了175毫秒,但是如果我通过循环替换乘法步骤,那么它会很快(191微秒),即

def transform (x) :
    x = x.iloc[::-1]
    for i in range(x.shape[0]) : 
        x['a'].values[i] = x['a'].values[i] * 2
    return x

我愿意使用第二个函数(即使第一个函数更“优雅”),但我想知道将来在不影响效率的情况下反转行顺序的最佳方法是什么?为什么这样做发生。

谢谢!

编辑:我添加了更多代码来帮助-我基本上是在试图了解这些功能之间的区别:

import numpy as np
import pandas as pd

y = pd.DataFrame({'a' : np.arange(5), 'b' : np.arange(5)})

def transform_1 (x) : 
    x = x.iloc[::-1]
    x['a'] = x['a'] * 2
def transform_2 (x) :
    x = x.iloc[::-1]
    for i in range(x.shape[0]) :
        x['a'].values[i] = x['a'].values[i] * 2

%timeit transform_1(y.copy())
%timeit transform_2(y.copy())

39.9 ms ± 614 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
238 µs ± 5.19 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

长话短说,我有一个函数以一些数据帧作为输入,但是对于特定情况,我想传递经过特定转换(类似于乘以2)的反向数据帧,但是我注意到该函数比平常慢得多。我试图理解为什么反转数据帧然后尝试应用转换是如此之慢。

编辑2:

def transform_3 (x) :
    x = x.iloc[::-1]
    x['a'] *= 2
def transform_4 (x) :
    x = x.sort_index(axis = 0, ascending = False)
    x['a'] = x['a'] * 2

%timeit transform_3(y.copy())
%timeit transform_4(y.copy())
41.1 ms ± 1.19 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
536 µs ± 9.91 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

1 个答案:

答案 0 :(得分:1)

我不太确定我是否了解您要尝试做的事情,但是我将以您在问题中使用的示例为例

x = pd.DataFrame({'a' : np.arange(5), 'b' : np.arange(5)})

结果(第一列是索引):

|    |   a |   b |
|----|-----|-----|
|  0 |   0 |   0 |
|  1 |   1 |   1 |
|  2 |   2 |   2 |
|  3 |   3 |   3 |
|  4 |   4 |   4 |

接下来,我们调用您的函数(transform的任一版本)

transform(x)

结果:

|    |   a |   b |
|----|-----|-----|
|  0 |   0 |   0 |
|  1 |   2 |   1 |
|  2 |   4 |   2 |
|  3 |   6 |   3 |
|  4 |   8 |   4 |

因此,基本上,您在进行计算之前就颠倒了行的顺序,但是如果不这样做,结果将是相同的。

在任何情况下,您也可以使用sort_values来反转表而无需遍历表。

x.rename_axis(index='idx').sort_values(by='idx', 
                                       axis=0, 
                                       ascending=False)

由于必须将索引级别的名称传递给sort_values,因此首先必须调用rename_axis来分配名称(可以是任何名称,在此示例中,我选择了idx )。

或者,您也可以使用sort_index(性能类似):

x.sort_index(axis='index', ascending=False)

因此:

def transform_simple(x) :
    x['a'] *= 2
    return x

x = pd.DataFrame({'a' : np.arange(500), 'b' : np.arange(500)})
transform_simple(x.sort_index(axis='index', ascending=False))

计时结果(500行):

transform (1st version): 81.9 ms ± 2.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
transform (2nd version): 4.23 ms ± 319 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
transform_simple: 1.55 ms ± 147 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)