2011-11-21 235 views
48

我想了解如何在不使用循環的情況下條件替換數據框中的值。我的數據幀結構如下:條件替換data.frame中的值

> df 
      a b est 
1 11.77000 2 0 
2 10.90000 3 0 
3 10.32000 2 0 
4 10.96000 0 0 
5 9.90600 0 0 
6 10.70000 0 0 
7 11.43000 1 0 
8 11.41000 2 0 
9 10.48512 4 0 
10 11.19000 0 0 

dput輸出是這樣的:

structure(list(a = c(11.77, 10.9, 10.32, 10.96, 9.906, 10.7, 
11.43, 11.41, 10.48512, 11.19), b = c(2, 3, 2, 0, 0, 0, 1, 2, 
4, 0), est = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), .Names = c("a", 
"b", "est"), row.names = c(NA, -10L), class = "data.frame") 

我想要做的,是檢查的b值。如果b爲0,我想將est設置爲值a。據我所知df$est[df$b == 0] <- 23est的所有值設置爲23,當時b==0。我不明白的是當條件爲真時如何將est設置爲值a。例如:

df$est[df$b == 0] <- (df$a - 5)/2.533 

給出了以下警告:

Warning message: 
In df$est[df$b == 0] <- (df$a - 5)/2.533 : 
    number of items to replace is not a multiple of replacement length 

有沒有我可以通過相關的細胞,而不是向量的方法嗎?

回答

53

既然你有條件索引df$est,你還需要有條件指數更換矢量df$a

index <- df$b == 0 
df$est[index] <- (df$a[index] - 5)/2.533 

當然,可變index只是暫時的,我用它來使代碼多一點可讀。你可以把它寫在一個步驟:

df$est[df$b == 0] <- (df$a[df$b == 0] - 5)/2.533 

爲了更好的可讀性,您可以使用within:哪種方法

df <- within(df, est[b==0] <- (a[b==0]-5)/2.533) 

的結果,不管你選擇:

df 
      a b  est 
1 11.77000 2 0.000000 
2 10.90000 3 0.000000 
3 10.32000 2 0.000000 
4 10.96000 0 2.352941 
5 9.90600 0 1.936834 
6 10.70000 0 2.250296 
7 11.43000 1 0.000000 
8 11.41000 2 0.000000 
9 10.48512 4 0.000000 
10 11.19000 0 2.443743 

正如其他人已經指出的,在您的示例中的替代解決方案是使用ifelse

11

這裏有一種方法。 ifelse是向量化的,它檢查所有行的零值爲b,並用(a - 5)/2.53代替est(如果是這種情況)。

df <- transform(df, est = ifelse(b == 0, (a - 5)/2.53, est)) 
5

R-inferno或基本的R-文檔將解釋爲什麼使用df $ *不是這裏最好的方法。在「[」的幫助頁面中:「

」通過[索引]不同之處在於$不允許計算指數,而[[。x $ name等價於x [[「name」,exact = FALSE]]。另外,[[可以使用精確參數控制部分匹配行爲。「

我推薦使用[row,col]表示法。例如:

Rgames: foo 
     x y z 
    [1,] 1e+00 1 0 
    [2,] 2e+00 2 0 
    [3,] 3e+00 1 0 
    [4,] 4e+00 2 0 
    [5,] 5e+00 1 0 
    [6,] 6e+00 2 0 
    [7,] 7e+00 1 0 
    [8,] 8e+00 2 0 
    [9,] 9e+00 1 0 
    [10,] 1e+01 2 0 
Rgames: foo<-as.data.frame(foo) 

Rgames: foo[foo$y==2,3]<-foo[foo$y==2,1] 
Rgames: foo 
     x y  z 
1 1e+00 1 0e+00 
2 2e+00 2 2e+00 
3 3e+00 1 0e+00 
4 4e+00 2 4e+00 
5 5e+00 1 0e+00 
6 6e+00 2 6e+00 
7 7e+00 1 0e+00 
8 8e+00 2 8e+00 
9 9e+00 1 0e+00 
10 1e+01 2 1e+01 
+0

這值得一給予好評,如果你第一次添加或者是鏈接到R-地獄頁或者用'$'(或者理想情況下都是)來總結問題。 – Andrie

+0

+1雖然我認爲在這種情況下'''運算符是完美無缺的。 (另外,我注意到,儘管你的警告你自己使用'''...) – Andrie

+0

@Andrie:是的,我在它的工作原理中使用過它(這不是那麼有幫助:-))。 OP試圖用它來定義哪些元素正在被執行,哪些是故障發生的地方。我只是用它來定義一個選擇數據框元素的條件。但你知道這一點:-) –

24

嘗試data.table:=操作:

DT = as.data.table(df) 
DT[b==0, est := (a-5)/2.533] 

它的快速和短暫。查看:=更多信息,這些鏈接的問題:

Why has data.table defined :=

When should I use the := operator in data.table

How do you remove columns from a data.frame

R self reference

+0

美麗,感謝參考+1的一切。 – PKumar

+0

非常有用的迴應。如果使用這個,請確保注意DT不是data.table包中的函數,而是數據表對象的引用。 –