2015-12-17 41 views
2

我有一個數據框,df,2列。當我創建第三列並嘗試僅更新第一個值時,它會填充整個列。有人能解釋這是爲什麼嗎?解決方案是什麼?爲什麼新數據幀列會填充所有值?

​​3210

上面的代碼產生以下結果:

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

由於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指出了這一點)。

+0

我想如果你在乾淨的會議中運行你的最後一個例子,你可能會發現它不會像OP期望的那樣工作_quite_。 – joran

+0

謝謝@RobertH。我像你推薦的'df $職業< - NA'那樣初始化了新的專欄,並且做了這個訣竅。我沒有在'data.frame()'函數中包含佔位矢量,但它仍然有效。 – heyydrien

1

這給預期的輸出,如果你不想前初始化變量:

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

我不知道爲什麼...

+0

你可以通過(非常長的)''[< - 。data.frame''來查看它的工作原理,但祝你好運,只需要1-3個字符就可以跟蹤所有的變量名! ;) – joran

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,所以「a」沿着每一行被回收。

這看起來很簡單,但是當我們發生了什麼(請確保每個它們之間全殲列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的第一,第二等元素。

現在運行:

> `[<-`(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 

,你可以開始看到各種調用是如何被拼湊起來。

相關問題