如何在 pandas 中以 dplyr 的方式分组、汇总和过滤数据框?

3

我目前正在学习pandas,我之前对R/dplyr/tidyverse很熟悉。

pandas的API并不是那么直观易用,我该如何使用pandas语法优雅地重写dplyr中的操作?

library("nycflights13")
library("tidyverse")

delays <- flights %>%
  group_by(dest) %>%
  summarize(
    count = n(),
    dist = mean(distance, na.rm = TRUE),
    delay = mean(arr_delay, na.rm = TRUE)
  ) %>%
  filter(count > 20, dest != "HNL")
2个回答

5

pd.DataFrame.agg 方法本身不允许对列名进行灵活更改。

但实际上并非如此。您可以像在 R 中一样在 agg 内部重命名列,尽管最好不要将列名命名为 count,因为它也是一个属性:

    delays = (
    flights
    .groupby('dest', as_index=False)
    .agg(
        count=('year', 'count'),
        dist=('distance', 'mean'),
        delay=('arr_delay', 'mean'))
    .query('count > 20 & dest != "HNL"')
    .reset_index(drop=True)
)

2
哇,非常感谢。我一直在苦思冥想,认为没有办法使用“agg”进行这种列命名。 - Pedro Vinícius

2
我们可以编写一个Pandas函数和方法的串联,从而得到相同的数据帧/表格:
delays = (
    flights
    .groupby('dest', as_index=False)
    .agg({
        'year': 'count',
        'distance': 'mean',
        'arr_delay': 'mean',
    })
    .rename(columns={
        'year': 'count',
        'distance': 'dist',
        'arr_delay': 'delay',
    })
    .query('count > 20 & dest != "HNL"')
    .reset_index(drop=True)
)

更加冗长:Pandas的pd.DataFrame.agg方法在方法本身中不允许对列名进行灵活更改。

但它与Pandas所允许的一样优雅、简洁和清晰。


1
非常好。我唯一的担忧与 .query() 相关 -- 它比常规的 df.loc[df.col.values > ..., ] 慢得多。 - Alex
谢谢。关于.query(),我参考了Jake VanderPlas的《Python数据科学手册》中有关高性能Pandas的章节。您有关于query()性能的任何文本吗? - Pedro Vinícius
我在这里看到了测试链接,然后自己进行了相同结果的测试。这很令人沮丧,因为我喜欢query的语法和类似SQL的外观。 - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接