为什么新数据框列填充所有值?

时间:2015-12-17 22:54:48

标签: r dataframe

我有一个数据框,df,有2列。当我创建第3列并尝试仅更新第一个值时,它会填充整个列。有人可以解释为什么会这样,解决方案是什么?

#Create data frame with 2 columns and 4 observations
name <- c("Bob", "Lauren", "Joe", "Chris")
age <- c(45, 34, 54, 12)
df <- data.frame(name, age)

#Create new column
df$occupation[1] <- "Builder"

上面的代码产生以下结果:

    df
    name age occupation
1    Bob  45    Builder
2 Lauren  34    Builder
3    Joe  54    Builder
4  Chris  12    Builder

期望的结果是:

 df
    name age occupation
1    Bob  45    Builder
2 Lauren  34       <NA>
3    Joe  54       <NA>
4  Chris  12       <NA>

谢谢!

3 个答案:

答案 0 :(得分:3)

由于occupation尚未存在,因此会回收第一个值。我就是这样做的。

name <- c("Bob", "Lauren", "Joe", "Chris")
age <- c(45, 34, 54, 12)
df <- data.frame(name, age, occupation=NA)

df$occupation <- NA
df$occupation[1] <- "Builder"

df <- data.frame(name, age, occupation=NA)
df$occupation[1] <- "Builder"

请注意

df <- data.frame(name, age)
df$occupation[2] <- "Builder"

也可以按预期工作。它会回收c(NA, "Builder")(感谢@joran指出这一点)。

答案 1 :(得分:2)

我认为这可以使用更多的澄清。

考虑设置:

name <- c("Bob", "Lauren", "Joe", "Chris")
age <- c(45, 34, 54, 12)
df <- data.frame(name, age)

现在看看我们这样做会发生什么:

debugonce(`$<-.data.frame`)
> df$x[1] <- "a"
debugging in: `$<-.data.frame`(`*tmp*`, "x", value = "a")
debug: {
    cl <- oldClass(x)
    class(x) <- NULL
    nrows <- .row_names_info(x, 2L)
    if (!is.null(value)) {
        N <- NROW(value)
        if (N > nrows) 
            stop(sprintf(ngettext(N, "replacement has %d row, data has %d", 
                "replacement has %d rows, data has %d"), N, nrows), 
                domain = NA)
        if (N < nrows) 
            if (N > 0L && (nrows%%N == 0L) && length(dim(value)) <= 
                1L) 
                value <- rep(value, length.out = nrows)
            else stop(sprintf(ngettext(N, "replacement has %d row, data has %d", 
                "replacement has %d rows, data has %d"), N, nrows), 
                domain = NA)
        if (is.atomic(value) && !is.null(names(value))) 
            names(value) <- NULL
    }
    x[[name]] <- value
    class(x) <- cl
    return(x)
}

请注意,这是通过value = "a"调用的,最终我们只需运行x[[name]] <- value,因此&#34; a&#34;在每一行都被回收。

这看起来很简单,但是当我们这样做时会发生什么(务必在每个列之间消除x列!):

debugonce(`$<-.data.frame`)
> df$x[2] <- "a"
debugging in: `$<-.data.frame`(`*tmp*`, "x", value = c(NA, "a"))
#Rest snipped...

大穗!这一次是用value = c(NA,"a")调用的,所以与RobertH的上述答案相反,我们看到回收实际上产生了:

> df
    name age    x
1    Bob  45 <NA>
2 Lauren  34    a
3    Joe  54 <NA>
4  Chris  12    a

困惑?如果我们尝试怎么办?

debugonce(`$<-.data.frame`)
> df$x[3] <- "a"
debugging in: `$<-.data.frame`(`*tmp*`, "x", value = c(NA, NA, "a"))

嗯。这个结束时出错,因为回收失败了。

完成:

debugonce(`$<-.data.frame`)
> df$x[4] <- "a"
debugging in: `$<-.data.frame`(`*tmp*`, "x", value = c(NA, NA, NA, "a"))

那导致:

> df
    name age    x
1    Bob  45 <NA>
2 Lauren  34 <NA>
3    Joe  54 <NA>
4  Chris  12    a

那么这里发生了什么?好吧,请记住,数据框中不存在的列(或列表中不存在的元素,实际上)被视为NULL。因此,我们引用NULL的第1个,第2个等元素。

现在运行:

> `[<-`(NULL,1,1)
[1] 1
> `[<-`(NULL,2,1)
[1] NA  1
> `[<-`(NULL,3,1)
[1] NA NA  1
> `[<-`(NULL,4,1)
[1] NA NA NA  1

您可以开始查看各种调用是如何拼凑在一起的。

答案 2 :(得分:1)

如果您不希望在以下情况下初始化变量,则会给出预期输出:

df[1,"occupation"] <- "Builder"

我不知道为什么......