【问题标题】:Split a value in a cell and add to a newly created row in R拆分单元格中的值并添加到 R 中新创建的行
【发布时间】:2013-03-23 01:25:59
【问题描述】:

我有一个数据集,我需要评估具有相同 id 代码的多个条目,如果满足一组条件,则在最后一行拆分一个单元格值。

条件 = 该 id 的最后一行具有 action=="l" & time >60。

如果满足此条件,我想更改行操作

样本数据集

id <- c("12_1","12_1","12_1","12_2","12_2","12_2")
action <- c("l","d","l","l","d","l")
time <- c(15,45,90,20,30,61)
dtfrm <-data.frame(cbind(id,action,time))

测试数据框

    id action time
1 12_1      l   15
2 12_1      d   45
3 12_1      l   90
4 12_2      l   20
5 12_2      d   30
6 12_2      l   61

我希望转换后的数据框看起来像这样

    id action time
1 12_1      l   15
2 12_1      d   45
3 12_1      e   60
4 12_1      l   30
5 12_2      l   20
6 12_2      d   30
7 12_2      e   60
8 12_2      l    1

最终,我将有更复杂的条件来评估,但我试图从简单的开始,逐步提高将这个数据集调整为工作顺序所需的更复杂的条件。谢谢。

【问题讨论】:

    标签: r if-statement conditional-statements


    【解决方案1】:

    我会编写一个对一组“id”进行操作的函数:

    process.one <- function(df) {
      n <- nrow(df)
      last.action <- df$action[n]
      last.time   <- df$time[n]
      if (last.action == "l" & last.time > 60) {
        next.row <- df[n, ]
        next.row$action = "l"
        next.row$time   = last.time - 60
        df <- rbind(df, next.row)
        df$action[n] <- "e"
        df$time[n]   <- 60
      }
      df
    }
    

    然后使用plyr进行分割/应用/合并:

    ddply(dtfrm, "id", process.one)
    #     id action time
    # 1 12_1      l   15
    # 2 12_1      d   45
    # 3 12_1      e   60
    # 4 12_1      l   30
    # 5 12_2      l   20
    # 6 12_2      d   30
    # 7 12_2      e   60
    # 8 12_2      l    1
    

    还要确保您的 data.frame 没有因子,否则附加到它可能会出现问题。在顶部,它应该是:

    dtfrm <- data.frame(id, action, time, stringsAsFactors = FALSE)
    

    【讨论】:

    • 感谢您的回复。我的真实数据框有 46 列。有没有办法“复制”上一行中的所有值并且只更改操作和时间,或者我需要添加这些额外的列名以及我希望它们如何填充到公式中?
    • 感谢您的努力。我想从这个开始我可以修改你的答案并在我的附加条件中工作,但我遇到了一些麻烦。我现在需要评估上面的行,并且仅在该行 action=="d" 时进行修改。我想我可以创建 previous.action
    • 就像你说的,但它应该是previous.action &lt;- df$action[n-1]。这也假设每个组至少有两行,如果不是这样,您需要检查n &gt; 1
    • n 多次等于 1,是否不应该评估为 NA 因此仍然允许函数在 previous.action=="NA" 时运行?
    【解决方案2】:

    这有点牵扯,但应该这样做:

    # fix the time column, it should be numeric
    dtfrm[, "time"] <- as.numeric(as.character(dtfrm[, "time"]))
    
    library(data.table)
    DT <- data.table(cbind(dtfrm, rowid=seq(nrow(dtfrm))), key="id")
    
    # identify which rows need modification
    DT[, needsMod := FALSE]
    DT[unique(DT[, "id", with=FALSE])
       ,  needsMod := {L <- length(action); (action[L] == "l" && time[L] > 60)  }
       , by=id
       , mult="last"]
    
    # append new rows
    DT <- setkey(rbind(DT, 
           DT[c(needsMod), list(id, action, time=time-60, rowid=rowid+1e-2, needsMod=!needsMod)]), 
           id, rowid)
    
    # modify the identified rows
    DT[c(needsMod), c("action", "time") := list("e", 60)]
    
    # optionally remove added columns, though personally, I would keep some form of rowid
    DT[ , c("needsMod", "rowid") := NULL]
    DT
    
    #      id action time
    # 1: 12_1      l   15
    # 2: 12_1      d   45
    # 3: 12_1      e   60
    # 4: 12_1      l   30
    # 5: 12_2      l   20
    # 6: 12_2      d   30
    # 7: 12_2      e   60
    # 8: 12_2      l    1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-16
      • 2021-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多