python - 在 pandas 数据帧上链接方法时,列引用语法看似不一致

标签 python r pandas dplyr

我有点困惑,为什么在 pandas 数据框中引用列的语法会因调用的方法而异。采取以下示例方法链

import pandas as pd

iris = pd.read_csv('https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv')
iris.columns = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Species']
(iris
    .loc[:, ['SepalLength', 'PetalWidth', 'Species']]
    .where(iris['SepalLength'] > 4.6)
    .assign(PetalWidthx2 = lambda x_iris: x_iris['PetalWidth'] * 2)
    .groupby('Species')
    .agg({'SepalLength': 'mean', 'PetalWidthx2': 'std'}))

在这里,使用三种不同的语法来引用 iris 数据框中的列:

  • locgroupbyagg 都理解字符串是指数据框中的列。
  • where 需要显式引用数据框。
  • assign 方法中显式引用数据框会导致操作在原始 iris 数据框上执行,而不是通过调用 loc 修改的副本哪里。这里需要lambda来引用修改后的数据帧副本的当前状态。
  • 除了上面还有query,将整个方法输入为一个字符串:iris.query('SepalLength > 4.6'),但这里的 pandas 文档明确指出这是针对特殊用例的:

    A use case for query() is when you have a collection of DataFrame objects that have a subset of column names (or index levels/names) in common. You can pass the same query to both frames without having to specify which frame you’re interested in querying

为了提供我所说的一致数据框列引用语法的示例,可以与 R 包 dplyr 进行比较,其中数据框中的列使用相同的语法进行引用对于所有管道函数调用。

library(dplyr)

# The iris data set is preloaded in R
colnames(iris) = c('SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Species')
iris %>% 
    select(SepalLength, PetalWidth, Species) %>% 
    filter(SepalLength > 4.6) %>%  
    mutate(PetalWidth2x = PetalWidth * 2) %>% 
    group_by(Species) %>% 
    summarise(SepalLength = mean(SepalLength), PetalWidth2x = sd(PetalWidth2x))

pandas 使用这些不同的方式引用数据框列,而不是应用 locgroupby 使用的简单语法,是否有优势? agg 到所有方法(如果是这样,这些好处是什么)?或者,这更多是针对在 assignwhere 方法中使用字符串作为数据框列名称的一些潜在问题的解决方法?

最佳答案

引自Marius's评论:

I think the biggest difference between pandas and dplyr is that pandas works within Python's existing syntax rules, which are pretty strict with respect to what unquoted symbols can represent (basically objects in the current scope)...

我相信这是正确的,所以让我们稍微扩展一下。


loc, groupby, and agg all understand that a string refers to a column in the data frame.

.loc[:, ['SepalLength', 'PetalWidth', 'Species']]
.groupby('Species')
.agg({'SepalLength': 'mean', 'PetalWidthx2': 'std'}))

在所有这三种情况下,字符串都是该上下文中的有效实体。也就是说,字符串本身就提供了足够的信息来执行操作。不像……


where needs the data frame to be explicitly referenced.

.where(iris['SepalLength'] > 4.6)

where的情况下, Python 需要运算符 >对某事进行操作。通过选择特定的数据框列,该列引用了一个对象,__gt__将针对该对象调用方法。

如果我们希望语法看起来像这样:

.where('SepalLength' > 4.6)

我们需要一些方法来告诉 Python > 是什么运营商意味着在这种情况下。评估发生在传递给 where 之前.现有的语言功能是提供我们自己的对象,并定义适当的方法,这就是 pandas 设计者所做的。默认 >在此上下文中,对字符串的操作没有用。


Explicitly referring to the data frame in the assign method would cause the operation to be performed on the original iris data frame, and not the copy that has been modified by the calls to loc and where. Here, lambda is needed to refer to the current state of the modified data frame copy.

.assign(PetalWidthx2 = lambda x_iris: x_iris['PetalWidth'] * 2)

如果.assign将被用作数据框的第一个方法,在进行任何过滤之前,我们可以简单地将其写为

.assign(PetalWidthx2 = iris['PetalWidth'] * 2)

由于变量iris已经存在并且与我们要操作的数据框相同。

但是,由于之前调用了 .loc.where更改我们希望调用的数据框 .assign上,它不再与 iris 相同数据框,并且没有定义的变量引用修改后的数据框。由于 pandas 使用 Python 现有的语法规则,它可以利用 lambda ,在这种情况下,它基本上允许对 self 进行操作: 对象的当前状态 .assign被调用。有 an example of this in the docs .

这使用了方法的 **kwargs,它允许指定任意数量的参数(新列名)及其参数(新列的值)。 **kwargs parameter=argument对在内部解释为字典 key:value对,如 the source 中所示.


In addition to the above, there is also query, which takes the entire method input as a string: iris.query('SepalLength > 4.6'), but here the pandas documentation explicitly states that this is for special use cases

query的情况下,传递的字符串是一个表达式,将由通常比执行 python 代码快得多的后端编译和执行。这是一个特殊情况,因为可用的操作非常有限,而且后端引擎的设置时间很长,所以它实际上只对相当大的数据集有用。

关于python - 在 pandas 数据帧上链接方法时,列引用语法看似不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44060100/

相关文章:

python - 单击按钮时如何打开新的子窗口? (wxpython)

r - 如何从包含n * NA的数据框中删除行

R:如何清除所有警告

pandas - PostgreSQL "upsert"pd.DataFrame.to_sql 插入方法中如何获取主键列

python - 当我点击矩形时连续移动它(pygame)

python - TensorFlow 2 中自定义层的 call() 中的 tf.while_loop()

python - 内存使用,使用 Dict 与使用键和值列表填充 Pandas DataFrame

lapply 的 R 变量列表导致错误 : "argument is not numeric or logical: returning NA"

python - 跨多个日期列进行插值

python - Pandas 分组和计数