2011-02-23 80 views
8

我想要做的是令人尷尬的簡單 - 但我失敗了。乘以一個data.frame的每個單元格與它的重量

我有一個data.frame與「字符」和「數字」。 data.frame的其中一列代表權重。

我想乘以數據框的每個單元格與相應的權重(如果它是一個數字)。

我該怎麼做(最好不使用嵌套循環)。

預先感謝您!

例子:

c1 c2 w 
l1 abc 2 1 
l2 dxf 3 0.5 
l3 ghi 4 1.5 

應該成爲

c1 c2 w 
l1 abc 2 1 
l2 dxf 1.5 0.5 
l3 ghi 6 1.5 

回答

6

對於重現的實例中,dd是具有可變類型的混合物的數據幀,與正在W的權重。

dd <- data.frame(G=gl(2,2), X=rnorm(4), Y=1L:4L, Z=letters[1:4], W=0.3:3.3) 
num.vars <- names(dd)[sapply(dd, is.numeric)] #select numeric variables 
num.vars <- setdiff(num.vars, "W") # remove the weight variable 
dd[num.vars] <- dd[num.vars] * dd$W # multiply 
+0

這看起來很棒! – speendo 2011-02-23 14:27:04

+0

優秀的技術提取數字列,然後重新插入它們。謝謝! – drbv 2012-09-12 19:09:44

5

Vectorise!

> dat <- data.frame(c1 = c("abc","dxf","ghi"), c2 = 2:4, w = c(1,0.5,1.5)) 

實際上,你想c2 * w,但我們需要讓R看看數據幀:

> with(dat, c2 * w) 
[1] 2.0 1.5 6.0 

,我們可以插回到dat在單行:

> dat <- within(dat, c3 <- c2 * w) 
> dat 
    c1 c2 w c3 
1 abc 2 1.0 2.0 
2 dxf 3 0.5 1.5 
3 ghi 4 1.5 6.0 

(如果要覆蓋現有的01,請將c3替換爲。)

如果除了權重以外還有多個數字列,那麼如果要自動執行它,則需要一個簡單的策略。不告訴R哪些列乘以w)。

> ## dummy data 
> dat2 <- data.frame(c1 = c("abc","dxf","ghi"), c2 = 2:4, w = c(1,0.5,1.5), 
        c3 = 5:7, c4 = 3:5) 
> ## select the columns we want, all numerics, but not `w` 
> want <- sapply(dat2, is.numeric) & names(dat2) != "w" 
> ## then use want to index into dat2 
> dat2[, want] <- with(dat2, dat2[, want] * w) 
> dat2 
    c1 c2 w c3 c4 
1 abc 2.0 1.0 5.0 3.0 
2 dxf 1.5 0.5 3.0 2.0 
3 ghi 6.0 1.5 10.5 7.5 
+0

謝謝!我知道這會起作用,但我有大約200列,所以我不能手工做所有這些多元化。但我想有一種方法可以通過apply或foreach循環來實現... – speendo 2011-02-23 14:25:51

+1

@Marcel我最初並沒有注意到Q的許多列部分 - 我添加了一個爲許多列做同樣事情的例子同時你正在寫你的評論。 – 2011-02-23 14:33:16

+0

我的錯 - 在我最初的問題中沒有提到它 – speendo 2011-02-23 14:40:21

2

只是出於樂趣,試圖使其在同一行(但實際上不是最可讀!):

R> dd <- data.frame(G=gl(2,2), X=rnorm(4), Y=1L:4L, Z=letters[1:4], W=0.3:3.3) 
R> dd 
    G   X Y Z W 
1 1 0.2319565 1 a 0.3 
2 1 0.4242205 2 b 1.3 
3 2 0.5218064 3 c 2.3 
4 2 0.7155944 4 d 3.3 

R> data.frame(lapply(subset(dd, select=-W), function(v, w=dd$W) { if (is.numeric(v)) v*w else v }), W=dd$W) 
    G   X Y Z W 
1 1 0.06958695 0.3 a 0.3 
2 1 0.55148670 2.6 b 1.3 
3 2 1.20015475 6.9 c 2.3 
4 2 2.36146163 13.2 d 3.3 
+0

我以某種方式嘗試了你,但我失敗了!我會仔細看看這個! :) – speendo 2011-02-23 14:33:36

1

正如你所看到的,這樣做多種方式,但不知何故,你會期望一個非常簡單的方法,我不知道這是否存在。 plyr軟件包中有一個名爲colwise的庫函數,但我無法想出一個乾淨的方法來實現您想要的功能。我可以做wtih colwise最好的是這個(假設你的數據框被命名爲DF):

w2<-df$w df<-colwise(function(x,w){if(is.numeric(x)){x*w} else{x}})(df,df$w) df$w<-w2

對於那些誰熟悉colwise,我不認爲你可以簡單地使用numcolwise因爲那時非數字列根本不發射。而且我無法弄清楚任何干淨的方式都不會讓乘法運算符合重量,這就是爲什麼我在這裏簡單地保存和恢復它的原因。我認爲如果能夠制定出更清晰的方法,colwise是一個很好的方法,並且易於理解。

+0

謝謝!我真的認爲有一個簡單的命令可以完成所有的事情,但是沒關係,至少我學到了一些東西...... – speendo 2011-02-27 01:43:00

相關問題