【问题标题】:Unlist an object in R but replace numeric(0) with NAs取消列出 R 中的对象,但将 numeric(0) 替换为 NA
【发布时间】:2018-04-10 09:44:25
【问题描述】:

我目前有一个数据框,每列都有暗名。在大多数情况下,这不是问题,但我最近在其中添加了一个新列 qgf,由于某种原因,它被作为列表而不是向量读入。

这是几行的示例:

> wc_results_data[12:20, 23]
$wc_1930_Uruguay
numeric(0)

$wc_1930_USA
numeric(0)

$wc_1934_Argentina
numeric(0)

$wc_1934_Austria
[1] 6

$wc_1934_Belgium
[1] 6

$wc_1934_Brazil
numeric(0)

$`wc_1934_Czech Republic/CSFR`
[1] 2

$wc_1934_Egypt
[1] 11

$wc_1934_France
[1] 6

如您所见,wc_results_data[c(12:14, 17, 23] 当前编码为 numeric(0),而实际上它们应该是 NAs(我应该澄清一下,在我的代码中也有 0 的实际 值 )。

这些值的真正奇怪的是,如果我尝试这样测试它们,我会得到奇怪的结果:

> wc_results_data[12,23]
$wc_1930_Uruguay
numeric(0)
> identical(wc_results_data[12,23], numeric(0))
[1] FALSE
> length(wc_results_data[12,23])
[1] 1

为了尝试解决此问题,我尝试使用 unlist 保存此列:

wc_results_data[,23]

但我收到此错误:

replacement has 368 rows, data has 425

这当然是有道理的,基本上我有 57 个观察结果是 numeric(0),但我无法摆脱它们。有没有办法unlist 并将这些numeric(0) 观察结果存储为NAs?谁能告诉我我做错了什么?

根据下面的评论,这是我在 data.frame 的几行和几列上对dput 的输出:

dput( wc_results_data[12:20, 22:24])
structure(list(fgd = structure(c(12, 1, -1, 0, -3, -2, 3, -2, 
-1), .Dim = 9L, .Dimnames = list(c("wc_1930_Uruguay", "wc_1930_USA", 
"wc_1934_Argentina", "wc_1934_Austria", "wc_1934_Belgium", "wc_1934_Brazil", 
"wc_1934_Czech Republic/CSFR", "wc_1934_Egypt", "wc_1934_France"
))), qgf = structure(list(wc_1930_Uruguay = numeric(0), wc_1930_USA = numeric(0), 
    wc_1934_Argentina = numeric(0), wc_1934_Austria = 6, wc_1934_Belgium = 6, 
    wc_1934_Brazil = numeric(0), `wc_1934_Czech Republic/CSFR` = 2, 
    wc_1934_Egypt = 11, wc_1934_France = 6), .Dim = 9L, .Dimnames = list(
    c("wc_1930_Uruguay", "wc_1930_USA", "wc_1934_Argentina", 
    "wc_1934_Austria", "wc_1934_Belgium", "wc_1934_Brazil", "wc_1934_Czech Republic/CSFR", 
    "wc_1934_Egypt", "wc_1934_France"))), qga = structure(list(
    wc_1930_Uruguay = numeric(0), wc_1930_USA = numeric(0), wc_1934_Argentina = numeric(0), 
    wc_1934_Austria = 1, wc_1934_Belgium = 8, wc_1934_Brazil = numeric(0), 
    `wc_1934_Czech Republic/CSFR` = 1, wc_1934_Egypt = 2, wc_1934_France = 1), .Dim = 9L, .Dimnames = list(
    c("wc_1930_Uruguay", "wc_1930_USA", "wc_1934_Argentina", 
    "wc_1934_Austria", "wc_1934_Belgium", "wc_1934_Brazil", "wc_1934_Czech Republic/CSFR", 
    "wc_1934_Egypt", "wc_1934_France")))), .Names = c("fgd", 
"qgf", "qga"), row.names = 12:20, class = "data.frame")

【问题讨论】:

  • numeric(0) 不是数字 0 而是长度为 0 的数字向量。由于它们的长度为 0,您可以测试该功能。假设wc_results_data 是一个数据框,那么wc_results_data[12:20, 23] 的输出非常奇怪。数据框行通常不会显示为列表成员。如果您发布 dput( wc_results_data[12:20, 22:24]) 的输出,将更好地支持编写代码来解决此问题
  • 是的,这真的很奇怪。我刚刚将dput 的输出添加到主帖中
  • 您能否也包括您的预期输出。我不清楚你想做什么。在您的示例数据中,qgf 和 qga 列包含 lists。您只是想删除零长度条目但保留lists,还是要取消列表中的条目?
  • @MauritsEvers 我想取消嵌套列表中的条目,以便我可以将这些 numeric(0) 值“重新编码”为 NAs
  • 感谢您的澄清;我添加了一个潜在的解决方案。

标签: r list numeric


【解决方案1】:

我将dput 输出分配给名称wc_results_data,这是打印输出:

wc_results_data
   fgd qgf qga
12  12        
13   1        
14  -1        
15   0   6   1
16  -3   6   8
17  -2        
18   3   2   1
19  -2  11   2
20  -1   6   1

str 在有问题的列上的结果是:

str(wc_results_data$qgf)
List of 9
 $ wc_1930_Uruguay            : num(0) 
 $ wc_1930_USA                : num(0) 
 $ wc_1934_Argentina          : num(0) 
 $ wc_1934_Austria            : num 6
 $ wc_1934_Belgium            : num 6
 $ wc_1934_Brazil             : num(0) 
 $ wc_1934_Czech Republic/CSFR: num 2
 $ wc_1934_Egypt              : num 11
 $ wc_1934_France             : num 6
 - attr(*, "dim")= int 9
 - attr(*, "dimnames")=List of 1
  ..$ : chr [1:9] "wc_1930_Uruguay" "wc_1930_USA" "wc_1934_Argentina" "wc_1934_Austria" ...

我需要在该列上使用sapply 来“应用”length 函数:

is.na( wc_results_data$qgf) <- sapply( wc_results_data$qgf, length) == 0
> wc_results_data
   fgd qgf qga
12  12  NA    
13   1  NA    
14  -1  NA    
15   0   6   1
16  -3   6   8
17  -2  NA    
18   3   2   1
19  -2  11   2
20  -1   6   1

您可能需要先使用此方法遍历所有列,然后才能对其进行修改,使其行为类似于常规数据框。仅在这些列上使用 unlist 无法生成可用于数据框的结果。

【讨论】:

    【解决方案2】:

    如果我理解正确,这里是dplyr 解决方案:

    library(tidyverse);
    df %>%
        mutate(
            qgf = unlist(ifelse(sapply(qgf, length) == 0, NA, qgf)),
            qga = unlist(ifelse(sapply(qga, length) == 0, NA, qga)))
    #  fgd qgf qga
    #1  12  NA  NA
    #2   1  NA  NA
    #3  -1  NA  NA
    #4   0   6   1
    #5  -3   6   8
    #6  -2  NA  NA
    #7   3   2   1
    #8  -2  11   2
    #9  -1   6   1
    

    实际上,dplyr 唯一的依赖是 mutate,所以基本 R 解决方案同样简单:

    df$qgf <- unlist(ifelse(sapply(df$qgf, length) == 0, NA, df$qgf));
    df$qga <- unlist(ifelse(sapply(df$qga, length) == 0, NA, df$qga));
    

    样本数据

    df <- structure(list(fgd = structure(c(12, 1, -1, 0, -3, -2, 3, -2,
    -1), .Dim = 9L, .Dimnames = list(c("wc_1930_Uruguay", "wc_1930_USA",
    "wc_1934_Argentina", "wc_1934_Austria", "wc_1934_Belgium", "wc_1934_Brazil",
    "wc_1934_Czech Republic/CSFR", "wc_1934_Egypt", "wc_1934_France"
    ))), qgf = structure(list(wc_1930_Uruguay = numeric(0), wc_1930_USA = numeric(0),
        wc_1934_Argentina = numeric(0), wc_1934_Austria = 6, wc_1934_Belgium = 6,
        wc_1934_Brazil = numeric(0), `wc_1934_Czech Republic/CSFR` = 2,
        wc_1934_Egypt = 11, wc_1934_France = 6), .Dim = 9L, .Dimnames = list(
        c("wc_1930_Uruguay", "wc_1930_USA", "wc_1934_Argentina",
        "wc_1934_Austria", "wc_1934_Belgium", "wc_1934_Brazil", "wc_1934_Czech Republic/CSFR",
        "wc_1934_Egypt", "wc_1934_France"))), qga = structure(list(
        wc_1930_Uruguay = numeric(0), wc_1930_USA = numeric(0), wc_1934_Argentina = numeric(0),
        wc_1934_Austria = 1, wc_1934_Belgium = 8, wc_1934_Brazil = numeric(0),
        `wc_1934_Czech Republic/CSFR` = 1, wc_1934_Egypt = 2, wc_1934_France = 1), .Dim = 9L, .Dimnames = list(
        c("wc_1930_Uruguay", "wc_1930_USA", "wc_1934_Argentina",
        "wc_1934_Austria", "wc_1934_Belgium", "wc_1934_Brazil", "wc_1934_Czech Republic/CSFR",
        "wc_1934_Egypt", "wc_1934_France")))), .Names = c("fgd",
    "qgf", "qga"), row.names = 12:20, class = "data.frame")
    

    【讨论】:

      【解决方案3】:

      这是tidyverse的一个选项

      library(tidyverse)
      df %>% 
         mutate_at(2:3, funs(map(., ~ .x[1]) ))
      #  fgd qgf qga
      #1  12  NA  NA
      #2   1  NA  NA
      #3  -1  NA  NA
      #4   0   6   1
      #5  -3   6   8
      #6  -2  NA  NA
      #7   3   2   1
      #8  -2  11   2
      #9  -1   6   1
      

      上面将列保留为list,但如果需要将其作为常规列,请使用map_dbl

      df %>%
          mutate_at(2:3, funs(map_dbl(., ~ .x[1]) ))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-08
        • 2021-07-02
        • 2017-07-30
        • 2021-10-15
        • 1970-01-01
        • 1970-01-01
        • 2020-11-19
        • 2016-01-09
        相关资源
        最近更新 更多