我想通过值向量将数据框中的多个列相乘。值的特定向量根据另一列中的值而变化。
- 编辑 -
如果我使数据集更复杂,即超过2个条件并且条件随机地在数据集周围移动,该怎么办?
以下是我的数据集示例:
df=data.frame(
Treatment=(rep(LETTERS[1:4],each=2)),
Species=rep(1:4,each=2),
Value1=c(0,0,1,3,4,2,0,0),
Value2=c(0,0,3,4,2,1,4,5),
Value3=c(0,2,4,5,2,1,4,5),
Condition=c("A","B","A","C","B","A","B","C")
)
看起来像:
Treatment Species Value1 Value2 Value3 Condition
A 1 0 0 0 A
A 1 0 0 2 B
B 2 1 3 4 A
B 2 3 4 5 C
C 3 4 2 2 B
C 3 2 1 1 A
D 4 0 4 4 B
D 4 0 5 5 C
如果Condition=="A"
,我想将第3-5列乘以向量c(1,2,3)
。如果Condition=="B"
,我想将第3-5列乘以向量c(4,5,6)
。如果Condition=="C"
,我想将第3-5列乘以向量c(0,1,0)
。因此,结果数据框将如下所示:
Treatment Species Value1 Value2 Value3 Condition
A 1 0 0 0 A
A 1 0 0 12 B
B 2 1 6 12 A
B 2 0 4 0 C
C 3 16 10 12 B
C 3 2 2 3 A
D 4 0 20 24 B
D 4 0 5 0 C
我已尝试对数据框进行子集化并乘以向量:
t(t(subset(df[,3:5],df[,6]=="A")) * c(1,2,3))
但是我无法将子集化数据帧返回到原始数据帧。有没有办法在不对数据框进行子集化的情况下执行此操作,以便保留其他列(例如,处理,物种)?
答案 0 :(得分:9)
这是一个相当普遍的解决方案,您应该能够适应您的需求。
注意outer
调用中的第一个参数是逻辑向量,第二个参数是数字,因此在乘法TRUE
和FALSE
转换为1
和{{}之前1}},分别。我们可以添加0
结果,因为条件不重叠,outer
元素将为零。
FALSE
答案 1 :(得分:2)
编辑以反映评论中的一些注释
假设Condition
是一个因素,你可以这样做:
#Modified to reflect OP's edit - the same solution works just fine
m <- matrix(c(1:6,0,1,0),3,3,byrow = TRUE)
df[,3:5] <- with(df,df[,3:5] * m[Condition,])
使用相当快速的矢量化乘法。很明显,在with
中包装它并不是绝对必要的,它正是从我的大脑中突然出现的。另请注意Backlin下面的子集评论。
在全球范围内,请记住,您可以使用subset
执行每个子集,也可以使用[
,而且至关重要的是[
支持通过[<-
进行分配。因此,如果您想要更改数据框或矩阵的一部分,您可以随时使用这种类型的习语:
df[rowCondition,colCondition] <- <replacement values>
当然假设<replacement values>
与您的df
子集的维度相同。它可能会起作用,但是你会违反R的回收规则,R可能会发出警告。
答案 2 :(得分:2)
这是一个非矢量化但易于理解的解决方案:
replaceFunction <- function(v){
m <- as.numeric(v[3:5])
if (v[6]=="A")
out <- m * c(1,2,3)
else if (v[6]=="B")
out <- m * c(4,5,6)
else
out <- m
return(out)
}
g <- apply(df, 1, replaceFunction)
df[3:5] <- t(g)
df
答案 3 :(得分:1)
df[3:5] <- df[3:5] * t(sapply(df$Condition, function(x) if(x=="B") 4:6 else 1:3))
或通过向量乘法
df[3:5] <- df[3:5] * (3*(df$Condition == "B") %*% matrix(1, 1, 3)
+ matrix(1:3, nrow(df), 3, byrow=T))