首页 文章

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

提问于
浏览
4

我想用数值向量乘以数据框中的几列 . 值的特定向量根据另一列中的值而变化 .

  • 编辑 -

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

  • 8

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

    注意 outer 调用中的第一个参数是逻辑向量,第二个参数是数字,因此在乘法之前 TRUEFALSE 分别转换为 10 . 我们可以添加 outer 结果,因为条件不重叠且 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
    
  • 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
    
  • 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,])
    

    它使用了相当快速的矢量化乘法 . 很明显,把它包装在_2897193中并不是我大脑中出现的东西 . 另请注意Backlin下面的子集评论 .

    更全局,请记住,您可以使用 subset 执行的每个子集也可以使用 [ ,而且至关重要的是, [ 支持通过 [<- 进行分配 . 因此,如果您想要更改数据框或矩阵的一部分,您可以始终使用这种类型的习语:

    df[rowCondition,colCondition] <- <replacement values>
    

    当然假设 <replacement values>df 的子集具有相同的维度 . 它可能会起作用,但是你会违反R的回收规则,R可能会发出警告 .

  • 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))
    

相关问题