通过不同的向量乘以数据帧的各种子集

时间:2011-07-29 20:50:06

标签: r vector subset multiplying

我想通过值向量将数据框中的多个列相乘。值的特定向量根据另一列中的值而变化。

- 编辑 -

如果我使数据集更复杂,即超过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))

但是我无法将子集化数据帧返回到原始数据帧。有没有办法在不对数据框进行子集化的情况下执行此操作,以便保留其他列(例如,处理,物种)?

4 个答案:

答案 0 :(得分:9)

这是一个相当普遍的解决方案,您应该能够适应您的需求。

注意outer调用中的第一个参数是逻辑向量,第二个参数是数字,因此在乘法TRUEFALSE转换为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))