Почему group_by -> filter -> суммировать в R быстрее, чем pandas? - PullRequest
1 голос
/ 03 июня 2019

Я конвертирую некоторые из наших старых кодов из R в Python.В процессе выяснилось, что панды немного медленнее, чем R. Интересно узнать, что я делаю не так.

R Код (в моей системе около 2 мс):

df = data.frame(col_a = sample(letters[1:3],20,T),
           col_b = sample(1:2,20,T),
             col_c = sample(letters[1:2],20,T),
             col_d = sample(c(4,2),20,T)
             )

microbenchmark::microbenchmark(
a = df %>% 
  group_by(col_a, col_b) %>% 
  summarise(
    a = sum(col_c == 'a'),
    b = sum(col_c == 'b'),
    c = a/b
  ) %>% 
  ungroup()
)

панд (10 мс в моей системе):

df = pd.DataFrame({
    'col_a': np.random.choice(['a','b','c'],N),
    'col_b': np.random.choice([1,2],N),
    'col_c': np.random.choice(['a', 'b'],N),
    'col_d': np.random.choice(['4', '2'],N),
})
%%timeit 
df1 = df.groupby(['col_a', 'col_b']).agg({
    'col_c':[
        ('a',lambda x: (x=='a').sum()),
        ('b',lambda x: (x=='b').sum())
    ]}).reset_index()
df1['rat'] = df1.col_c.a/df1.col_c.b

1 Ответ

1 голос
/ 03 июня 2019

Это не технический ответ, но стоит отметить, что существует множество различных способов выполнить эту операцию в Пандах, и некоторые из них быстрее, чем другие. Например, приведенный ниже код Pandas возвращает искомые значения (хотя и с некрасивыми столбцами MultiIndex) примерно за 5 мс:

df.groupby(['col_a', 'col_b', 'col_c'])\
  .count()\
  .unstack()\
  .assign(rat = lambda x: x.col_d.a/x.col_d.b)

4.96 ms ± 169 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Помимо любых повышений скорости под капотом, я думаю, что главное преимущество в скорости синтаксиса tidyverse перед Pandas заключается в том, что summarise() сделает каждую новую переменную доступной сразу же в рамках одного и того же вызова, что исключает необходимость spread рассчитывает и затем вычисляет rat.

Если есть аналог этого в Пандах, я этого не знаю. Ближайшая вещь это либо pipe(), либо использование lambda в assign(). Каждый новый вызов функции в цепочке требует времени для выполнения, поэтому Pandas работает медленнее.

...