代码之家  ›  专栏  ›  技术社区  ›  Primusa

为什么熊猫的索引速度这么慢?如何加快速度?

  •  0
  • Primusa  · 技术社区  · 6 年前

    运行此代码将显示大熊猫和常规python列表之间的速度差异:

    ser = pd.Series(range(100))
    lst = ser.tolist()
    
    for _ in range(10):
        pandas_time = 0
        list_time = 0
        for _ in range(100000):
            r = randint(0, len(ser)-1)
            t = time()
            ser[r]
            pandas_time += time() - t
    
            t = time()
            lst[r]
            list_time += time() - t
    
        print(pandas_time, list_time)
    

    结果(10次随机元素索引试验100000次):

    Pandas             Regular List
    0.6404812335968018 0.03125190734863281
    0.6560468673706055 0.0
    0.5779874324798584 0.01562190055847168
    0.5467743873596191 0.015621662139892578
    0.6106545925140381 0.004016399383544922
    0.5866603851318359 0.029597759246826172
    0.7981059551239014 0.016004562377929688
    0.8128316402435303 0.013040542602539062
    0.5566465854644775 0.021578073501586914
    0.6386256217956543 0.00500178337097168
    

    为熊猫系列编制索引的速度似乎比python列表慢30-100倍。为什么?我们怎样才能加快速度?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Primusa    6 年前

    我检查过了 pandas' 源代码。这个 __getitem__ 与常规的python列表相比,pandas系列中的实现有很多额外的业务逻辑,因为pandas系列支持使用列表和iterables进行索引。

    为熊猫系列编制索引时,该系列:

    1. 尝试应用可调用的密钥

    2. 获取该键处索引的值(听起来足够简单,但请记住,该索引是另一个pandas对象,它还必须支持比常规索引更多的索引)

    3. 检查2)是否为标量

    4. 如果是标量,则返回结果

    这些额外的步骤减慢了 第二章 与常规的python列表相比,效果显著。

    要解决这个问题,您可以直接使用底层的numpy数组。这里我们使用 ser.values 改为索引:

    ser = pd.Series(range(100))
    lst = ser.tolist()
    
    ser = ser.values
    
    for _ in range(10):
        pandas_time = 0
        list_time = 0
        for _ in range(1000000):
            r = randint(0, len(ser)-1)
            t = time()
            ser[r]
            pandas_time += time() - t
    
            t = time()
            lst[r]
            list_time += time() - t
    
        print(pandas_time, list_time)
    

    索引1000000个随机元素10次后,我们发现使用 .values 比索引熊猫系列快得多,但比使用python列表慢得多

    pd.Series.values    Regular List
    0.18845057487487793 0.04786252975463867
    0.10950899124145508 0.11034011840820312
    0.048889875411987305 0.09512066841125488
    0.17272686958312988 0.1406867504119873
    0.14252233505249023 0.048066139221191406
    0.06352949142456055 0.07906699180603027
    0.1405477523803711 0.07815265655517578
    0.18746685981750488 0.08007645606994629
    0.1405184268951416 0.0781564712524414
    0.07921838760375977 0.1412496566772461
    

    总结使用 价值观 当您需要快速索引大熊猫系列时,是一种方法。虽然看起来像 .tolist() 更快,请记住,在索引单个元素时,它只会稍微快一点。numpy数组将支持更快的花式索引,比如使用多个元素进行索引。