【问题标题】:Index and assign multiple sets of rows at once一次索引并分配多组行
【发布时间】:2021-04-01 13:11:28
【问题描述】:

我有一个导入的数据框 Measurements,其中包含来自实验的许多观察结果。

Measurements <- data.frame(X = 1:4,
           Data = c(90, 85, 100, 105))
X   Data
1   90          
2   85          
3   100         
4   105 

我想添加另一列 Condition,指定每个数据点的治疗组。我知道哪个观察范围来自哪个条件(例如,观察1:2 来自对照组,观察3:4 来自实验组)。

我已经设计了两种解决方案,它们可以提供所需的输出,但都不是理想的。第一:

Measurements["Condition"] <- c(rep("Cont", 2), rep("Exp", 2))
X   Data Condition      
1   90   Cont       
2   85   Cont       
3   100  Exp        
4   105  Exp

这样做的好处是一行代码/一个命令。但这并不理想,因为我需要在外面单独进行数学运算(例如 3:4 = 2 obs 等),这对于更大的数据集和更多条件(例如 47:83)可能是棘手/不清楚/间接 = ? obs 等)并且可能会导致永久错误,因为早期分配的长度上的小错误也会改变后面组的分配(例如,如果 Cont 的 rep 错误地为 1,则 Exp也被错误地分配到 2:3)。

我也想过这样分配,这也给出了所需的输出

Measurements[1:2, "Condition"] <- "Cont"
Measurements[3:4, "Condition"] <- "Exp"
X   Data Condition      
1   90   Cont       
2   85   Cont       
3   100  Exp        
4   105  Exp

这使得哪些行将接收哪些分配更加清晰/简单/直接,但这需要单独的分配和重复。我觉得应该有一种方法可以“矢量化”这个作业,这就是我正在寻找的解决方案

我无法从网上找到复杂的索引规则。这是我对如何实现这一目标的第一个直观猜测

Measurements[c(1:2, 3:4), "Condition"] <- list("Cont", "Exp")

X   Data Condition
1   90   Cont
2   85   Cont       
3   100  Cont       
4   105  Cont

但这不起作用。它似乎将 1:2 和 3:4 组合成一个等效范围 (1:4),并且仅将第一个条件分配给该范围,这表明我还需要再次指定该列。当我尝试再次指定列时:

Measurements[c(1:2, 3:4), c("Condition", "Condition")] <- list("Cont", "Exp")
X   Data Condition Condition.1    
1   90   Cont      Exp  
2   85   Cont      Exp  
3   100  Cont      Exp  
4   105  Cont      Exp

由于某种原因,这会创建第二个新列 (??),它似乎再次将 1:2 和 3:4 合并为本质上的 1:4。所以我认为我需要以一种保持它们分开的方式对 两个行范围 进行索引,并且只指定一次列,但我一直坚持如何做到这一点。我认为解决方案很简单,但我似乎找不到我正在尝试做的事情的例子。也许为了让它们分开,我确实必须分开分配它们,但我希望有办法。

有人可以帮忙吗?非常感谢 R noobie!

【问题讨论】:

    标签: r dataframe indexing set row


    【解决方案1】:

    如果您已经拥有属于每个条件的观察列表,您可以使用dplyr::case_when 进行条件变异。根据您存储此信息的方式,您可以使用以下内容:

    library(dplyr)
    
    Measurements <- data.frame(X = 1:4,
                               Data = c(90, 85, 100, 105))
    
    # set which observations belong to each condition
    Cont <- 1:2
    Exp <- 3:4
    
    Measurements %>%
      mutate(Condition = case_when(
        X %in% Cont ~ "Cont",
        X %in% Exp ~ "Exp"
      ))
    
    # X Data Condition
    # 1   90      Cont
    # 2   85      Cont
    # 3  100       Exp
    # 4  105       Exp
    

    请注意,这要求观察结果是连续的。

    【讨论】:

      【解决方案2】:

      对于较大的数据集而言,有效的方法是了解数据模式和数据 ID。

      Measurements <- data.frame(X = 1:4, Data = c(90, 85, 100, 105))
      dat <- c("Cont","Exp")
      pattern <- c(1,1,2,2)
      

      或者从数据中绘制模式,例如有条件的来自Measurements$Data

      pattern <- sapply( Measurements$Data >=100, function(x){ if(x){2}else{1} } )
      # [1] 1 1 2 2
      

      然后你可以简单地添加数据:

      Measurements$Condition <- dat[pattern]
      #  X Data Condition
      #1 1   90      Cont
      #2 2   85      Cont
      #3 3  100       Exp
      #4 4  105       Exp
      

      【讨论】:

        【解决方案3】:

        我通常看到这是通过合并操作完成的。诀窍是让您的条件数据形成良好的形状。

        composeConditions <- function(...) {
          conditions <- list(...)
          data.frame(
            X = unname(unlist(conditions)),
            condition = unlist(unname(lapply(
              names(conditions),
              function(x) rep(x, times = length(conditions[x][[1]]))
            )))
          )
        }
        
        conditions <- composeConditions(Cont = 1:2, Exp = 3:4)
        
        > conditions
        
          X condition
        1 1      Cont
        2 2      Cont
        3 3       Exp
        4 4       Exp
        
        merge(Measurements, conditions, by = "X")
        
          X Data condition
        1 1   90      Cont
        2 2   85      Cont
        3 3  100       Exp
        4 4  105       Exp
        

        【讨论】:

          猜你喜欢
          • 2020-08-15
          • 1970-01-01
          • 2023-03-13
          • 2013-08-18
          • 2023-03-17
          • 1970-01-01
          • 2018-11-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多