【问题标题】:R changing data frame columns value comparing with previous columnR与前一列相比更改数据框列值
【发布时间】:2018-03-29 00:11:01
【问题描述】:

我有一个大数据库,但对于这个练习,让我们使用这个:

    c-1    c-2   c-3  c-4  c-5 c-6  
   1-14  14-29  NA    NA   NA  NA
   60-90  CF    CF    CF   CF  CF
    C     1-14  14-29 CF   NA  NA
   60-90  CF    CF    CF   NA  NA

我想要的是将之前在列中获得 CF 的所有列更改为 HF,因此它看起来像这样:

   c-1    c-2   c-3  c-4  c-5 c-6  
   1-14  14-29  NA    NA   NA  NA
   60-90  CF    HF    HF   HF  HF
    C     1-14  14-29 CF   NA  NA
   60-90  CF    HF    HF   NA  NA

我尝试过这样的应用,但它不能正常工作

function_a <- function (x) {ifelse(df[,i]=="CF" & df[,i-1]=="CF", "HF", df[,i])}    
new_df<- as.data.frame(lapply(length(df):1, function_a))

请记住,如果上一列不是 CF,我想保留原始值,有没有简单的方法可以做到这一点?在 R 基础上?

【问题讨论】:

  • 所有列都是character吗?这是在所有列中,还是只是在特定分组或命名的列之上?

标签: r dataframe multiple-columns apply


【解决方案1】:

我喜欢这个问题,因为直接将其视为某种滚动应用,但不是zoo::rollapply 的意义(尽管它在那里也可能是可管理的)。我说的是Reduce(..., accumulate=TRUE)的使用。

您的数据:

dat <- data.frame(
  c1 = c('1-14','60-90','C','60-90'),
  c2 = c('14-29','CF','1-14','CF'),
  c3 = c(NA,'CF','14-29','CF'),
  c4 = c(NA,'CF','CF','CF'),
  c5 = c(NA,'CF',NA,NA),
  c6 = c(NA,'CF',NA,NA),
  stringsAsFactors = FALSE
)

我也在上一列中添加了检查"HF" 的逻辑,否则你会得到交替的"CF"/"HF"。我推断NA 应始终为NA,无论上一列如何,因为这就是您的示例的外观。 (这个假设很容易被删除。)

func <- function(a, b) ifelse(! is.na(a) & ! is.na(b) & a %in% c("CF","HF"), "HF", b)

默认情况下,Reduce 将只返回最后一列的结果。使用accumulate=TRUE,它会返回每次调用的结果(加上第一列),我们将使用它来重新填充相同大小的框架。

df[] <- Reduce(func, df, right=FALSE, accumulate=TRUE)
df
#      c1    c2    c3   c4   c5   c6
# 1  1-14 14-29  <NA> <NA> <NA> <NA>
# 2 60-90    CF    HF   HF   HF   HF
# 3     C  1-14 14-29   CF <NA> <NA>
# 4 60-90    CF    HF   HF <NA> <NA>

【讨论】:

    【解决方案2】:

    另一个建议的解决方案是转置矩阵,将矩阵滞后 1 行,然后检查滞后矩阵中的 CF 和转置矩阵中的 CF,最后转回以获得所需的输出:

    tdat <- t(dat)
    lagged <- rbind(matrix(NA_character_, ncol=nrow(dat)), tdat[-nrow(tdat),])
    tdat[lagged=="CF" & tdat=="CF"] <- "HF"
    res <- t(tdat)
    res
    

    数据:

    dat <- read.table(text="c-1    c-2   c-3  c-4  c-5 c-6  
    1-14  14-29  NA    NA   NA  NA
    60-90  CF    CF    CF   CF  CF
    C     1-14  14-29 CF   NA  NA
    60-90  CF    CF    CF   NA  NA", header=TRUE, check.names=FALSE)
    

    【讨论】:

      【解决方案3】:

      使用与原始数据大小相同的矩阵,查找在第一次出现后连续出现的"CF" 单元格:

      sel <- dat == "CF" & (!is.na(dat))
      dat[col(dat) > max.col(sel, "first") & sel] <- "HF"
      dat
      #    c-1   c-2   c-3  c-4  c-5  c-6
      #1  1-14 14-29  <NA> <NA> <NA> <NA>
      #2 60-90    CF    HF   HF   HF   HF
      #3     C  1-14 14-29   CF <NA> <NA>
      #4 60-90    CF    HF   HF <NA> <NA>
      

      使用@r2evans 的dat 对象。

      【讨论】:

        猜你喜欢
        • 2019-03-30
        • 2021-11-24
        • 2018-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-08
        • 1970-01-01
        • 2020-10-17
        相关资源
        最近更新 更多