df ["速度"]和df $速度之间的差异

时间:2017-12-27 05:26:01

标签: r dataframe

假设数据框df有一列speed,那么访问该列的方式有何不同:

df["speed"]

或者像这样:

df$speed

以下正确计算平均值:

lapply(df["speed"], mean) 

但是这会打印列速度下的所有值:

lapply(df$speed, mean)

2 个答案:

答案 0 :(得分:4)

OP中的问题有两个要素。第一个元素在评论中得到解决:df["speed"]data.frame()类型的对象,而df$speed是数字向量。我们可以通过str()函数看到这一点。

我们将用Ezekiel 1930年关于速度和停止距离的分析来说明这一点,即cars包中的datasets数据集。

> library(datasets)
> data(cars)
> 
> str(cars["speed"])
'data.frame':   50 obs. of  1 variable:
 $ speed: num  4 4 7 7 8 9 10 10 10 11 ...
> str(cars$speed)
 num [1:50] 4 4 7 7 8 9 10 10 10 11 ...
> 

评论中未解决的第二个要素是lapply()在传递向量与list()时的行为方式不同。

使用向量,lapply()可以独立处理向量中的每个元素,从而为mean()等函数生成意外结果。

> unlist(lapply(cars$speed,mean))
 [1]  4  4  7  7  8  9 10 10 10 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15
[26] 15 16 16 17 17 17 18 18 18 18 19 19 19 20 20 20 20 20 22 23 24 24 24 24 25

发生了什么事?

由于cars$speed的每个元素都由mean()独立处理,lapply()会返回50个均值的列表,每个数量为1个数字:cars$speed向量中的原始元素。

使用lapply()

处理列表

使用列表,列表的每个元素都是独立处理的。我们可以使用lapply()函数计算length()处理的项目数。

> length(cars["speed"])
[1] 1
>

由于数据框也是list(),其中包含data.frame()类型的一个元素,因此length()函数返回值1.因此,当由lapply()处理时,计算单个均值,而不是speed列的每一行。

> lapply(cars["speed"],mean)
$speed
[1] 15.4

> 

如果我们将整个cars数据帧作为lapply()的输入对象传递,我们在数据帧中每列获得一个均值,因为数据框中的两个变量都是数字。

> lapply(cars,mean)
$speed
[1] 15.4

$dist
[1] 42.98

> 

理论观点

lapply()的不同行为可以解释为R是一种面向对象的语言。事实上,R所基于的S语言的创建者John Chambers曾经说过:

  

在R中,两个标语很有帮助。

     

- 存在的一切都是一个对象,而且      - 发生的一切都是函数调用。

John Chambers,引自 Advanced R, p。 79。

lapply()在数据框上的工作方式与向量不同的事实是polymorphism的面向对象特征的说明,其中对不同类型的对象以不同的方式实现相同的行为。

答案 1 :(得分:2)

虽然这看起来像一个初学者的问题但我认为值得回答它,因为许多初学者可能有类似的问题,并且相应文档的指南是有用的恕我直言。

请不要投票 - 我只是收集有助于答案的问题中的评论片段 - 随时编辑此答案... *

  1. data.frame是具有相同长度(元素数量)的向量列表。请阅读R控制台中的帮助(通过键入?data.frame

  2. 通过将一列作为向量($

  3. 返回来实现?"$.data.frame"运算符
  4. lapply将函数应用于列表的每个元素(请参阅?lapply)。如果第一个参数X是一个包含多个元素的标量向量(整数,双...),向量的每个元素都被转换为("强制")到一个单独的列表元素(与as.list(1:26)相同)

  5. <强>示例:

    x <- data.frame(a = LETTERS, b = 1:26, stringsAsFactors = FALSE)
    b.vector <- x$b
    b.data.frame <- x["b"]
    class(b.vector)       # integer
    class(b.data.frame)   # data.frame
    
    lapply(b.vector, mean)
    # returns a result list with 26 list elements, the same as `lapply(1:26, mean)`
    # [[1]]
    # [1] 1
    # 
    # [[2]]
    # [1] 2
    # ... up to list element 26
    
    lapply(b.data.frame, mean)
    # returns a list where each element of the input vector in param X
    # becomes a separate list element (same as `as.list(1:26)`)
    # $b
    # [1] 13.5
    

    所以恕我直言,您的原始问题可以简化为:如果第一个参数是标量向量而不是列表,为什么lapply表现不同?