【问题标题】:Convert vector into 2-column dataframe with string-subsetting in R在 R 中使用字符串子集将向量转换为 2 列数据框
【发布时间】:2017-09-18 19:44:02
【问题描述】:

我认为我无法找到发布此问题的类似版本,因为我觉得这是一个相对独特的问题,但是如果我弄错了,请指出正确的方向。我正在使用以下需要转换为数据框的向量:

myvec = structure(c(1.03, 2.3, -1.2, -0.09, -0.31, -0.51, 3.4, 3, 0.07, 
0.02, 1.05, -0.02, 2.03), .Names = c("Intercept", "DEF-1017", 
"DEF-1025", "DEF-103", "DEF-1043", "DEF-1046", "DEF-1048", "DEF-1076", 
"OFF-1017", "OFF-1025", "OFF-103", "OFF-1046", "OFF-1076"))

head(myvec)
Intercept  DEF-1017  DEF-1025   DEF-103  DEF-1043  DEF-1046 
 1.03      2.30     -1.20     -0.09     -0.31     -0.51 

该向量应该具有 7 个不同用户(用户 1017、1025、103、1043、1046、1048、1076)的进攻(OFF)和防御(DEF)系数,但是缺少两个用户的进攻系数。我需要将其转换为具有 4 列(防御 ID、进攻 ID、防御系数、进攻系数)的数据框。更具体地说,我想获得以下数据框,以这种方式计算缺失值:

mydf = structure(list(DEFID = c("DEF-1017", "DEF-1025", "DEF-103", "DEF-1043", 
"DEF-1046", "DEF-1048", "DEF-1076"), OFFID = c("OFF-1017", "OFF-1025", 
"OFF-103", NA, "OFF-1046", NA, "OFF-1076"), DEFVAL = c(2.3, -1.2, 
-0.09, -0.31, -0.51, 3.4, 3), OFFVAL = c(0.07, 0.02, 1.05, NA, 
-0.02, NA, 2.03)), .Names = c("DEFID", "OFFID", "DEFVAL", "OFFVAL"
), row.names = c(NA, -7L), class = "data.frame")

mydf
     DEFID    OFFID DEFVAL OFFVAL
1 DEF-1017 OFF-1017   2.30   0.07
2 DEF-1025 OFF-1025  -1.20   0.02
3  DEF-103  OFF-103  -0.09   1.05
4 DEF-1043     <NA>  -0.31     NA
5 DEF-1046 OFF-1046  -0.51  -0.02
6 DEF-1048     <NA>   3.40     NA
7 DEF-1076 OFF-1076   3.00   2.03

截距值被删除/不包含在表中,其他所有内容都按预期格式化。对此的任何帮助将不胜感激,谢谢!

【问题讨论】:

    标签: r data-manipulation


    【解决方案1】:

    我将tidyr 包用于以下任务:

    首先转换为数据帧格式:

    library(tidyverse)
    df <- data_frame(names= names(myvec),
               values=myvec)
    

    接下来过滤掉拦截,并用tidyr命令重新排列:

    df %>% filter(names !="Intercept") %>% 
      extract(names, into=c("coeff", "user"), "([[:alnum:]]+)-([[:alnum:]]+)") %>% 
      spread(coeff, values) 
    # A tibble: 7 x 3
       user   DEF   OFF
    * <chr> <dbl> <dbl>
    1  1017  2.30  0.07
    2  1025 -1.20  0.02
    3   103 -0.09  1.05
    4  1043 -0.31    NA
    5  1046 -0.51 -0.02
    6  1048  3.40    NA
    7  1076  3.00  2.03
    

    如果您希望名称等与上面列出的完全相同,只需进一步处理:

    df %>% filter(names !="Intercept") %>% 
      extract(names, into=c("coeff", "user"), "([[:alnum:]]+)-([[:alnum:]]+)") %>% 
      spread(coeff, values) %>% 
      mutate(DEFID = paste("DEF", user, sep="-"),
             OFFID = paste("OFF", user, sep="-")) %>%
      rename(DEFVAL=DEF,
             OFFVAL=OFF) %>% 
      select(DEFID, OFFID, DEFVAL, OFFVAL)
    # A tibble: 7 x 4
         DEFID    OFFID DEFVAL OFFVAL
         <chr>    <chr>  <dbl>  <dbl>
    1 DEF-1017 OFF-1017   2.30   0.07
    2 DEF-1025 OFF-1025  -1.20   0.02
    3  DEF-103  OFF-103  -0.09   1.05
    4 DEF-1043 OFF-1043  -0.31     NA
    5 DEF-1046 OFF-1046  -0.51  -0.02
    6 DEF-1048 OFF-1048   3.40     NA
    7 DEF-1076 OFF-1076   3.00   2.03
    

    【讨论】:

      【解决方案2】:

      这正是您想要的。我使用了splitsubstrmerge。而且我认为这是一种最短的方法,可以提供您想要的输出。

       library(dplyr)
       DF <- tibble::rownames_to_column(data.frame(myvec))
       DF <- DF[DF$rowname!= "Intercept",]
       dff <- split(DF , f = substr(DF$rowname, 1, 3) )
       dff2 <- dff[[1]]; dff3 <- dff[[2]]
       dff2$ID <- substr(dff2$rowname, 5, nchar(dff2$rowname))
       dff3$ID <- substr(dff3$rowname, 5, nchar(dff3$rowname))
       DF2 <- merge(dff2,dff3,by="ID", all = TRUE)
       DF2 <- DF2[,c(2,4,3,5)]
       names(DF2) <- c("DEFID", "OFFID", "DEFVAL", "OFFVAL")
      
       DF2
      
          DEFID     OFFID    DEFVAL OFFVAL
       1 DEF-1017  OFF-1017   2.30   0.07
       2 DEF-1025  OFF-1025  -1.20   0.02
       3 DEF-103   OFF-103   -0.09   1.05
       4 DEF-1043      <NA>  -0.31     NA
       5 DEF-1046  OFF-1046  -0.51  -0.02
       6 DEF-1048      <NA>   3.40     NA
       7 DEF-1076  OFF-1076   3.00   2.03
      

      【讨论】:

        猜你喜欢
        • 2018-04-08
        • 1970-01-01
        • 1970-01-01
        • 2019-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-24
        • 1970-01-01
        相关资源
        最近更新 更多