【问题标题】:replace numeric(0) with 0 in R list用 R 列表中的 0 替换 numeric(0)
【发布时间】:2021-07-08 10:26:37
【问题描述】:

我有一个清单:

myList
$`0`
$`0`$item1
numeric(0)

$`0`$item2
[1] 350

$`0`$item3
numeric(0)


$`1`
$`1`$item1
numeric(0)

$`1`$item2
[1] 56

$`1`$item3
numeric(0)

我在这个列表中使用了一个 sapply 函数,但是得到一个错误:

参数的“类型”(列表)无效

我怎样才能像其他项目一样将所有numeric(0) 转换为 0?

【问题讨论】:

  • 请在列表中显示您正在使用的代码sapply。错误消息听起来像是错误在其他地方。
  • 仅供参考 sapply 是一个不可预测的函数。如果你知道你有一个列表进入和一个列表出来,使用lapply。对于其他输出,请尝试 purrr 中的 map 函数族

标签: r list sapply


【解决方案1】:

如果深度未知或不相等,您可以使用递归函数:

f <- function(x) {
  if(is.list(x)) lapply(x, f)
  else ifelse(length(x) == 0, 0, x)
}

f(myList)
#$`0`
#$`0`$item1
#[1] 0
#
#$`0`$item2
#[1] 350
#
#$`0`$item3
#[1] 0
#
#
#$`1`
#$`1`$item1
#[1] 0
#
#$`1`$item2
#[1] 56
#
#$`1`$item3
#[1] 0
#
#
#$`2`
#[1] 4
#
#$`3`
#[1] 0

数据:

myList <- list(`0` = list(item1 = numeric(0), item2 = 350, item3 = numeric(0)),
               `1` = list(item1 = numeric(0), item2 = 56, item3 = numeric(0)),
               `2` = 4, `3` = numeric(0))

【讨论】:

    【解决方案2】:

    假设您只有 1 个深度列表,这是最短的解决方案

    my_list[lengths(my_list) == 0] <- 0
    

    对于2个深度列表

    my_list <- lapply(my_list, function(x)x[lengths(x) == 0] <- 0)
    

    【讨论】:

    • 好点@KonradRudolph。忘了考虑推荐的多分配方法.. &lt;- .. &lt;- ..
    【解决方案3】:

    使用嵌套的lapply

    lapply(my_list, function(x) lapply(x, function(x) ifelse(length(x) == 0, 0, x)))
    $`0`
    $`0`$item1
    [1] 0
    
    $`0`$item2
    [1] 350
    
    $`0`$item3
    [1] 0
    
    
    $`1`
    $`1`$item1
    [1] 0
    
    $`1`$item2
    [1] 56
    
    $`1`$item3
    [1] 0
    

    sapplylapply

    lapply(my_list, function(x) sapply(x, function(x) ifelse(length(x) == 0, 0, x)))
    
    $`0`
    item1 item2 item3 
        0   350     0 
    
    $`1`
    item1 item2 item3 
        0    56     0 
    

    或在内部和外部使用sapply

    sapply(my_list, function(x) sapply(x, function(x) ifelse(length(x) == 0, 0, x)))
    
            0  1
    item1   0  0
    item2 350 56
    item3   0  0
    

    在名单上

    my_list <- list(`0` = list(item1 = numeric(0), item2 = 350, item3 = numeric(0)),
                    `1` = list(item1 = numeric(0), item2 = 56, item3 = numeric(0)))
    

    【讨论】:

      【解决方案4】:

      使用purrrmodify()

      newList <- purrr::modify(myList, ~ if(length(.) == 0){ 
                                         0 
                                         } else { . })
      

      或者使用base::lapply

      newList <- lapply(myList, function(x){
      if(length(x) == 0){
      out <- 0
      } else {
      out <- x
      }
      return(out)
      })
      

      【讨论】:

      • 为什么lapply 示例中的out 变量?只需使用与modify 相同的代码,它更干净、更易读(你也可以去掉多余的大括号)。
      • 只是习惯——我喜欢只有一个返回语句的函数。出于某种原因,我在使用 ~ f(.) 表示法时认为 /code 有所不同。
      • 您可能误解了我的评论,我不建议您拨打多个return。事实上,我建议不要使用return——这里是多余的(而不是好的那种多余的)。 Omitting the return call makes the code shorter and more readable 并消除了不必要的控制流:function (x) if (length(x) == 0L) 0 else x
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-13
      • 2020-09-06
      • 1970-01-01
      • 2021-06-09
      • 1970-01-01
      • 1970-01-01
      • 2016-10-26
      相关资源
      最近更新 更多