【问题标题】:R: Replacing values of one list element with values of a second list elementR:用第二个列表元素的值替换一个列表元素的值
【发布时间】:2019-06-27 11:31:23
【问题描述】:

我想用列表中第二个元素的值替换列表中一个元素的值。具体来说,

  • 我有一个包含多个数据集的列表。
  • 每个数据集有 2 个变量
  • 变量是因素
  • 每个数据集第二个变量的第n个元素需要替换成每个数据集第一个变量的第n个元素
  • 另外,被替换的值应该被称为“replaced”
  • dat1 <- data.frame(names1 =c("a", "b", "c", "f", "x"),values= c("val1_1", "val2_1", "val3_1", "val4_1", "val5_1"))
       dat1$values <- as.factor(dat1$values)
    dat2 <- data.frame(names1 =c("a", "b", "f2", "s5", "h"),values= c("val1_2", "val2_2", "val3_2", "val4_2", "val5_2"))
       dat2$values <- as.factor(dat2$values)
    list1 <- list(dat1, dat2)
    

    结果应该是相同的列表,但只是替换了第 5 个值。

    [[1]]
         names1  values
    1         a  val1_1
    2         b  val2_1
    3         c  val3_1
    4         f  val4_1
    5  replaced       x
    [[2]]
         names1  values
    1         a  val1_2
    2         b  val2_2
    3        f2  val3_2
    4        s5  val4_2
    5  replaced       h
    

    【问题讨论】:

    • 这是一个简化的例子。我有超过 4500 个数据集。

    标签: r list replace row


    【解决方案1】:

    这是tidyverse 的一个选项。循环遍历listmapslice感兴趣的行(在这种情况下,它是最后一行,所以n()可以使用),mutate列值并与原始数据绑定没有最后一行

    library(tidyverse)
    map(list1, ~ .x %>% 
                   slice(n()) %>%
                   mutate(values = names1, names1 = 'replaced') %>% 
                   bind_rows(.x %>% slice(-n()), .))
    #[[1]]
    #    names1 values
    #1        a val1_1
    #2        b val2_1
    #3        c val3_1
    #4        f val4_1
    #5 replaced      x
    
    #[[2]]
    #    names1 values
    #1        a val1_2
    #2        b val2_2
    #3       f2 val3_2
    #4       s5 val4_2
    #5 replaced      h
    

    或者可以使用来自forcatsfct_c 使其更紧凑。不同的factor 级别可以与fct_c 组合在一起用于'values' 和'names1' 列

    library(forcats)
    map(list1, ~ .x %>% 
            mutate(values = fct_c(values[-n()], names1[n()]), 
                   names1 = fct_c(names1[-n()], factor('replaced'))))
    

    或使用与base R 类似的方法,其中我们使用lapply 循环遍历list,然后将data.frame 转换为matrixrbind 矩阵的子集,即用值删除的最后一行感兴趣,然后转换为data.frame(默认为stringsAsFactors = TRUE - 所以它会转换为factor

    lapply(list1,  function(x)  as.data.frame(rbind(as.matrix(x)[-5, ], 
                  c('replaced',  as.character(x$names1[5])))))
    

    【讨论】:

    • 你如何得到行号,Akrun?上面的答案中使用了 n
    • @tobiassch 不,这里只有 5 行,n() 是最后一行。如果您有自定义 n,则在 slice(n) 中使用它
    • 是的!我明白了,会试试的!
    【解决方案2】:

    使用 lapply 的基本 R 方法,因为这两列都是我们需要先添加新的 levels 的因子,然后再用新值替换它们,否则这些值将变为 NAs。

    n <- 5
    
    lapply(list1, function(x) {
       levels(x$values) <- c(levels(x$values), as.character(x$names1[n]))
       x$values[n] <- x$names1[n]
       levels(x$names1) <- c(levels(x$names1), "replaced")
       x$names1[n] <- "replaced"
       x
    })
    
    #[[1]]
    #    names1 values
    #1        a val1_1
    #2        b val2_1
    #3        c val3_1
    #4        f val4_1
    #5 replaced      x
    
    #[[2]]
    #    names1 values
    #1        a val1_2
    #2        b val2_2
    #3       f2 val3_2
    #4       s5 val4_2
    #5 replaced      h
    

    还有另一种方法,我们可以将两列都转换为字符,然后替换所需位置的值并再次将它们转换回因子,但由于列表中的每个数据帧都可能很大,我们不想转换所有值到字符,然后返回因子只是为了更改一个值,这在计算上可能非常昂贵。

    【讨论】:

      猜你喜欢
      • 2015-02-12
      • 1970-01-01
      • 1970-01-01
      • 2014-03-14
      • 2011-09-07
      • 1970-01-01
      • 1970-01-01
      • 2017-07-05
      • 1970-01-01
      相关资源
      最近更新 更多