【问题标题】:Subtraction of a variable from a variable in the next row if certain conditions are met如果满足某些条件,则从下一行中的变量中减去变量
【发布时间】:2021-07-16 03:35:37
【问题描述】:

如果满足某些条件,我想从下一行的变量中减去一个变量。 考虑以下数据框:

time <- c(12, 14, 16, 10, NA, 18)
type <- c("morning", "noon", "evening", "morning", "noon", "evening")
data <- data.frame(time, type)

由于我的数据中有 4000 行,因此我需要一个包含两个变化值的循环(用于感兴趣的两行)。我还没有尝试实现循环,因为我很难在列中选择特定的行和特定的值。 (但我非常感谢有关如何包含循环的建议!) 到目前为止,代码如下所示:

if(data[which(data[row1, "type"] =="morning")] & data[which(data[row2, "type"] == "noon")]) | data[which(data[row1, "type"] =="noon")] & data[which(data[row2, "type"] == "evening")]) {
data[row2, "difference"] <- data[row2, "time"] - data[row1, "time"] 
}  else{
  data[row2, “difference"] <- NA
}

所以我想从row2中的时间减去row1中的时间值,并将结果存储在row2中的变量“difference”中。但是,只有满足两个条件之一时,才应减去这些值。

【问题讨论】:

  • 您的示例数据不起作用。您错过了向量开头的c,并且您有智能引号。同样cbind 将创建一个矩阵而不是data.frame。试试time &lt;- c(12, 14, 16, 10, NA, 18)type &lt;- c("morning", "noon", "evening", "morning", "noon", "evening")data &lt;- data.frame(time, type)

标签: r loops if-statement conditional-statements


【解决方案1】:

将 ThomasIsCoding 的优雅代码翻译成dplyr

library(dplyr)

df %>% group_by(grp = cumsum(type == 'morning')) %>%
  mutate(difference = c(NA, diff(time))) %>%
  ungroup() %>% select(-grp)

# A tibble: 6 x 3
   time type    difference
  <dbl> <chr>        <dbl>
1    12 morning         NA
2    14 noon             2
3    16 evening          2
4    10 morning         NA
5    NA noon            NA
6    18 evening         NA

【讨论】:

    【解决方案2】:

    这是另一种选择。 Lag 函数将允许检索前一行的值。

    library(data.table)
    library(dplyr)
    time <- c(12, 14, 16, 10, NA, 18)
    type <- c("morning", "noon", "evening", "morning", "noon", "evening")
    data <- data.table(time, type)
    data[,difference :=
     ifelse(((time > lag(time)) & (type == "noon") & (lag(type) == "morning")),time - lag(time),NA)]
    

    【讨论】:

    • 感谢您的评论!你的建议效果很好,除了只包括一个条件,例如,只计算早上和中午之间的滞后,而不是中午和晚上之间的滞后。
    【解决方案3】:

    diff 是两个值之间基本差异的主力函数。
    您可以一次性计算出所有差异,然后用NA覆盖那些不在您想要的比较中的差异@

    data$prevtype <- c(NA, head(data$type,-1)) 
    data$difference <- c(NA, diff(data$time))
    data$difference[!(
      (data$prevtype == "morning" & data$type == "noon") |
      (data$prevtype == "noon"    & data$type == "evening")
    )] <- NA
    data$prevtype <- NULL
    
    #  time    type difference
    #1   12 morning         NA
    #2   14    noon          2
    #3   16 evening          2
    #4   10 morning         NA
    #5   NA    noon         NA
    #6   18 evening         NA
    

    使用的数据:

    time <- c(12, 14, 16, 10, NA, 18)
    type <- c("morning", "noon", "evening", "morning", "noon", "evening")
    data <- data.frame(time, type, stringsAsFactors=FALSE)
    

    【讨论】:

    • 非常感谢您完美运行。也感谢您的简短解释!
    【解决方案4】:

    也许你可以试试这个

    transform(
      data,
      difference = ave(time, cumsum(type == "morning"), FUN = function(x) c(NA, diff(x)))
    )
    

    给了

      time    type difference
    1   12 morning         NA
    2   14    noon          2
    3   16 evening          2
    4   10 morning         NA
    5   NA    noon         NA
    6   18 evening         NA
    

    数据

    > dput(data)
    structure(list(time = c(12, 14, 16, 10, NA, 18), type = c("morning", 
    "noon", "evening", "morning", "noon", "evening")), class = "data.frame", row.names = c(NA,
    -6L))
    

    【讨论】:

    • 感谢您的评论!很遗憾,我不明白您的建议。
    猜你喜欢
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多