我有一个数据框,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>
谢谢!
答案 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"
我不知道为什么......