我想要做的就是让人感到尴尬 - 但我失败了。
我有一个带有“characters”和“numerics”的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
答案 0 :(得分: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
答案 1 :(得分: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
(如果您要覆盖现有的c3
,请将c2
替换为c2
。
如果你有一个以上的数字列而不是权重,如果你想自动化它就需要一个不同的策略(即不告诉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
答案 2 :(得分: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
答案 3 :(得分:1)
正如你所看到的,有很多方法可以做到这一点,但不知怎的,你会期待一种非常简单的方法,我不知道是否存在。 plyr包中有一个名为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就是一种很好的simlpe,也很容易理解。