【问题标题】:How to get this data structure in R?如何在 R 中获取此数据结构?
【发布时间】:2017-05-21 16:54:40
【问题描述】:

我正在尝试从当前数据结构中找到想要的数据结构。 我部分知道预期数据结构的示意图。 想要的数据结构还包括一个list(...)factor 类。 当前数据结构

> print(dat.m)

         [,1] [,2]
ave_max  150   61
ave       60    0
lepo      41    0

dat.m <- structure(c(150L, 60L, 41L, 61L, 0L, 0L), .Dim = c(3L, 2L), .Dimnames = list(
    c("ave_max", "ave", "lepo"), NULL))

想要的数据结构

> print(dat.m)

     Vars    M1    M2 
1 ave_max   150    61 
2 ave        60     0 
3 lepo       41     0 

我知道它示意性地类似于以下未知的structure(c(...)row.names = c(...)

structure(list(Vars = structure(c(...), .Label = c("ave_max", 
"ave", "lepo"), class = "factor"), M1 = c(150, 60, 
41), M2 = c(61, 0, 0)), .Names = c("Vars", "ave_max", "ave", 
"lepo"), class = "data.frame", row.names = c(...))

R:3.4.0(向后移植)
操作系统:Debian 8.7

【问题讨论】:

    标签: r data-structures


    【解决方案1】:

    如果您坚持将M1M2 等作为列名,还有一个更短的data.table 解决方案:

    library(data.table)   # CRAN version 1.10.4 used
    as.data.table(dat.m, keep.rownames = "Vars")
    #      Vars  V1 V2
    #1: ave_max 150 61
    #2:     ave  60  0
    #3:    lepo  41  0
    

    如果您这样做坚持将M1M2 等作为列名并且您的矩阵dat.m 有很多列,则可以重命名这些列:

    DT <- as.data.table(dat.m, keep.rownames = "Vars")
    setnames(DT, stringr::str_replace(names(DT), "^V(?=\\d+$)", "M"))
    DT
    #      Vars  M1 M2
    #1: ave_max 150 61
    #2:     ave  60  0
    #3:    lepo  41  0
    

    正则表达式使用前瞻断言来确保只有以V 开头并紧随其后并以至少一位数字结尾的列被更改。 VarsVV17bVV3 等其他人不会被触及。


    如果您的矩阵有很多列,并且您的操作目的不仅仅是为了打印漂亮的列标题,您可以考虑将数据从宽格式调整为长格式。例如,ggplot 首选长格式。

    DT_long <- melt(as.data.table(dat.m, keep.rownames = "Vars"), id.vars = "Vars")
    DT_long
    #      Vars variable value
    #1: ave_max       V1   150
    #2:     ave       V1    60
    #3:    lepo       V1    41
    #4: ave_max       V2    61
    #5:     ave       V2     0
    #6:    lepo       V2     0
    

    在长格式中,操作数据通常更容易,例如重命名列:

    DT_long[, variable := stringr::str_replace(variable, "^V", "M")]
    DT_long
    #      Vars variable value
    #1: ave_max       M1   150
    #2:     ave       M1    60
    #3:    lepo       M1    41
    #4: ave_max       M2    61
    #5:     ave       M2     0
    #6:    lepo       M2     0
    

    最后,你可以再次从长形重塑为宽形

    dcast(DT_long, Vars ~ ...)
    #      Vars  M1 M2
    #1:     ave  60  0
    #2: ave_max 150 61
    #3:    lepo  41  0
    

    请注意,转换公式识别 两个特殊变量:..... 表示无变量; ... 代表所有未在formula 中提及的变量。 (详见?data.table::dcast)。

    【讨论】:

    • @LéoLéopoldHertz준영 我已经添加了...的解释。
    • 在没有看到数据的情况下很难正确回答(参见minimal reproducible example)。请发布一个新问题并包含dput(DT_long) 的结果。谢谢。
    【解决方案2】:

    我们可以使用tidyverse

    library(tidyverse)
    dat.m %>% 
        as.data.frame() %>% 
        rownames_to_column('Vars') %>%
        rename(M1 = V1, M2 = V2)
    #     Vars  M1 M2
    #1 ave_max 150 61
    #2     ave  60  0
    #3    lepo  41  0
    

    如果我们需要使用data.table

    library(data.table)
    setnames(setDT(as.data.frame(dat.m), keep.rownames = TRUE), c('Vars', 'M1', 'M2'))[]
    

    【讨论】:

    • @LéoLéopoldHertz준영 我用data.table 方法更新了。我不确定您为什么会收到该消息。我有 data.table_1.10.5 和 dplyr 的开发版
    • 假设你有n的事件数量,这里只有两个。如何扩展setnames(setDT(as.data.frame(...)) 以覆盖M1M2、...、Mn
    • @LéoLéopoldHertz준영 你可以做setnames(setDT(as.data.frame(...)), c('Vars', paste0('M', seq_len(n))))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-02
    • 1970-01-01
    • 2018-12-28
    相关资源
    最近更新 更多