R 将数据帧的不同子集乘以不同的向量
我想将数据帧中的几列乘以一个值向量。值的特定向量根据另一列中的值而变化 --编辑-- 如果我将数据集变得更复杂,即超过2个条件,并且这些条件在数据集周围随机移动,该怎么办 以下是我的数据集示例:R 将数据帧的不同子集乘以不同的向量,r,vector,subset,multiplication,R,Vector,Subset,Multiplication,我想将数据帧中的几列乘以一个值向量。值的特定向量根据另一列中的值而变化 --编辑-- 如果我将数据集变得更复杂,即超过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
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”
,我想用向量c(1,2,3)
乘以第3-5列。如果Condition==“B”
,我想用向量c(4,5,6)
乘以第3-5列。如果Condition==“C”
,我想用向量C(0,1,0)
乘以第3-5列。因此,生成的数据帧如下所示:
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))
但我无法将子集数据帧返回到原始数据帧。是否有任何方法可以在不对数据框进行子集设置的情况下执行此操作,从而保留其他列(例如治疗、物种)?编辑以反映注释中的一些注释
假设条件
是一个因素,您可以这样做:
#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,])
当然,假设
与df
的子集的维度相同。否则它可能会起作用,但您将违反R的回收规则,R可能会发出警告。df[3:5]以下是一个非矢量化但易于理解的解决方案:
df[3:5] <- df[3:5] * t(sapply(df$Condition, function(x) if(x=="B") 4:6 else 1:3))
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
replaceFunction这里有一个相当通用的解决方案,您应该能够根据需要进行调整
请注意,outer
调用中的第一个参数是逻辑向量,第二个是数字,因此在乘法之前,TRUE
和FALSE
分别转换为1
和0
。我们可以添加外部
结果,因为条件是不重叠的,FALSE
元素将为零
multiples <-
outer(df$Condition=="A",c(1,2,3)) +
outer(df$Condition=="B",c(4,5,6)) +
outer(df$Condition=="C",c(0,1,0))
df[,3:5] <- df[,3:5] * multiples
multiples或者df[3:5]我完全同意as.integer
是不必要的。然而,我通常更喜欢在子集设置时明确表示我是否打算将其应用于行/列,但这是风格的问题。就我个人而言,我觉得这样读比较容易。但是,你总是可以挑剔这些东西到死。我的意思是,我使用和
来避免键入df$
!;)哈哈,没错。有时我会被尽可能地压缩所有的东西而得意忘形。但是与相比,它比df$
长一个字母毕竟,只要想想你浪费掉的那封信所能写的一切!嗯,很有趣的方法。如果我有多个条件,我将如何集成if-else语句?(见上图)我会选择joran建议的东西。用对应于每种可能情况的行制作一个矩阵,然后以某种巧妙的方式对它们进行索引。答案很好!这样做了,我终于能够成功地实现if-else语句。当我把它应用到更大的数据集时,R确实在df[3:5]=t(g)
之后发出了警告,但这些值在数据框中显示正确。+1确实需要让我的大脑围绕这些内部/外部函数。谢谢你的使用案例。虽然不太清楚它在做什么,但也很有效。谢谢
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
multiples <-
outer(df$Condition=="A",c(1,2,3)) +
outer(df$Condition=="B",c(4,5,6)) +
outer(df$Condition=="C",c(0,1,0))
df[,3:5] <- df[,3:5] * multiples