Подтвердить что ты не робот

Pandas Производительность DataFrame

Pandas действительно замечательный, но я действительно удивлен тем, насколько неэффективно это извлекать значения из Pandas.DataFrame. В следующем примере игрушек даже метод DataFrame.iloc более чем в 100 раз медленнее, чем словарь.

Вопрос: Является ли урок здесь только тем, что словари - лучший способ поиска ценностей? Да, я понимаю, именно это и было сделано. Но я просто задаюсь вопросом, есть ли что-то, что мне не хватает в производительности поиска DataFrame.

Я понимаю, что этот вопрос более "размышляет", чем "спрашивает", но я соглашусь с ответом, который дает представление или точку зрения на это. Спасибо.

import timeit

setup = '''
import numpy, pandas
df = pandas.DataFrame(numpy.zeros(shape=[10, 10]))
dictionary = df.to_dict()
'''

f = ['value = dictionary[5][5]', 'value = df.loc[5, 5]', 'value = df.iloc[5, 5]']

for func in f:
    print func
    print min(timeit.Timer(func, setup).repeat(3, 100000))

value = dictionary [5] [5]

0,130625009537

value = df.loc [5, 5]

+19,4681699276

value = df.iloc [5, 5]

+17,2575249672

4b9b3361

Ответ 1

A dict - это DataFrame, поскольку велосипед - автомобиль. Вы можете педалью на 10 футов на велосипеде быстрее, чем вы можете запустить автомобиль, получить его в снаряжении и т.д. И т.д. Но если вам нужно пройти милю, автомобиль победит.

В некоторых небольших целенаправленных целях диктовка может быть быстрее. И если это все, что вам нужно, тогда используйте dict, конечно! Но если вам нужна/нужна власть и роскошь DataFrame, то диктат не подменяет. Нецелесообразно сравнивать скорость, если структура данных не удовлетворяет ваши потребности в первую очередь.

Теперь, например, чтобы быть более конкретным - диктофон хорош для доступа к столбцам, но это не так удобно для доступа к строкам.

import timeit

setup = '''
import numpy, pandas
df = pandas.DataFrame(numpy.zeros(shape=[10, 1000]))
dictionary = df.to_dict()
'''

# f = ['value = dictionary[5][5]', 'value = df.loc[5, 5]', 'value = df.iloc[5, 5]']
f = ['value = [val[5] for col,val in dictionary.items()]', 'value = df.loc[5]', 'value = df.iloc[5]']

for func in f:
    print(func)
    print(min(timeit.Timer(func, setup).repeat(3, 100000)))

дает

value = [val[5] for col,val in dictionary.iteritems()]
25.5416321754
value = df.loc[5]
5.68071913719
value = df.iloc[5]
4.56006002426

Таким образом, список списков в 5 раз медленнее при поиске строк, чем df.iloc. Дефицит скорости увеличивается по мере роста числа столбцов. (Число столбцов похоже на число футов в аналогии с велосипедом. Чем дольше расстояние, тем удобнее автомобиль становится...)

Это лишь один пример того, когда диктофон списков будет менее удобным/медленным, чем DataFrame.

Еще один пример: если у вас есть DatetimeIndex для строк и вы хотите выбрать все строки между определенными датами. С помощью DataFrame вы можете использовать

df.loc['2000-1-1':'2000-3-31']

Для этого нет простого аналога, если вы использовали диктофон списков. И петли Python, которые вам нужно будет использовать для выбора правильных строк, снова будут очень медленными по сравнению с DataFrame.

Ответ 2

+1 для использования at или iat для скалярных операций. Пример теста:

In [1]: import numpy, pandas
   ...: df = pandas.DataFrame(numpy.zeros(shape=[10, 10]))
   ...: dictionary = df.to_dict()

In [2]: %timeit value = dictionary[5][5]
The slowest run took 34.06 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 310 ns per loop

In [4]: %timeit value = df.loc[5, 5]
10000 loops, best of 3: 104 µs per loop

In [5]: %timeit value = df.iloc[5, 5]
10000 loops, best of 3: 98.8 µs per loop

In [6]: %timeit value = df.iat[5, 5]
The slowest run took 6.67 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 9.58 µs per loop

In [7]: %timeit value = df.at[5, 5]
The slowest run took 6.59 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 9.26 µs per loop

Кажется, что использование at (iat) примерно в 10 раз быстрее, чем loc (iloc).

Ответ 3

Я столкнулся с той же проблемой. вы можете использовать at для улучшения.

"Поскольку индексирование с помощью [] должно обрабатывать множество случаев (одномаркетный доступ, нарезка, булевское индексирование и т.д.), у него есть немного накладных расходов, чтобы выяснить, что вы запрашиваете. для доступа к скалярному значению самым быстрым способом является использование методов at и iat, которые реализуются во всех структурах данных".

см. официальную ссылку http://pandas.pydata.org/pandas-docs/stable/indexing.html глава "Быстрое скалярное значение получения и настройки"

Ответ 4

У меня возникло различное явление о доступе к строке dataframe. проверьте этот простой пример на кадре данных около 10 000 000 строк. словарные камни.

def testRow(go):
    go_dict = go.to_dict()
    times = 100000
    ot= time.time()
    for i in range(times):
        go.iloc[100,:]
    nt = time.time()
    print('for iloc {}'.format(nt-ot))
    ot= time.time()
    for i in range(times):
        go.loc[100,2]
    nt = time.time()
    print('for loc {}'.format(nt-ot))
    ot= time.time()
    for i in range(times):
        [val[100] for col,val in go_dict.iteritems()]
    nt = time.time()
    print('for dict {}'.format(nt-ot))

Ответ 5

Я думаю, что самый быстрый способ доступа к ячейке -

df.get_value(row,column)
df.set_value(row,column,value) 

Оба быстрее, чем (я думаю)

df.iat(...) 
df.at(...)