代码之家  ›  专栏  ›  技术社区  ›  Haakonkas

用未知名称分隔列

  •  3
  • Haakonkas  · 技术社区  · 6 年前

    我有一个这样的数据框架:

    structure(list(header = 1:10, ST.adk.fumC.gyrB.icd.mdh.purA.recA = c(" 10 10 11 4 8 8 8 2", 
    " 48 6 11 4 8 8 8 2", " 58 6 4 4 16 24 8 14", " 88* 6* 4 12 1 20 12 7", 
    " 117 20 45 41 43 5 32 2", " 7036 526 7 1 1 8 71 6", " 101 43 41 15 18 11 7 6", 
    " 3595 112 11 5 12 8 88 86", " 117 20 45 41 43 5 32 2", " 744 10 11 135 8 8 8 2"
    )), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"
    ))
    

    我要做的是将第二列拆分为单独的列,用列名中的“.”分隔。然而,并不总是知道列的名称是什么,这就是为什么我不能在dplyr的“separate”函数中使用列的名称的原因。

    我尝试了以下方法:

    library(dplyr)
    library(stringr)
    library(tidyr)
    
    # get new column names
    ids <- unlist(strsplit(names(df)[-1],
                                  split = ".",
                                  fixed = TRUE))
    
    # get name of column to split
    split_column <- names(df)[-1]
    
    df %>%
    separate(split_column, into = ids, extra = "merge")
    

    这在我正在使用的脚本文件中有效,但当我源代码脚本时,会得到以下错误:

    Error: `var` must evaluate to a single number or a column name, not a character vector
    

    当我在rstudio中像正常一样运行它时,为什么这样做有效,但是当我源代码脚本时,它抛出了这个错误? 此外,这是将未知名称的列实际拆分为具有未知名称的新列的最佳方法吗?

    我在另一个脚本文件中使用以下代码来源代码:

    system(paste("Rscript script.R", opt$m, opt$o))
    

    其中opt$m和opt$o是目录路径。这对我使用的类似脚本很好,但是对于上面的脚本,它会抛出一个错误。

    我希望能有某种功能,比如独立的功能,但到目前为止还不存在。

    2 回复  |  直到 6 年前
        1
  •  1
  •   jay.sf    6 年前

    你可以使用 strsplit() .

    split <- do.call(rbind, strsplit(gsub("\\*", "", df[, -1]), " "))[, -1]
    df1 <- data.frame(df[, 1], split)
    df1[] <- lapply(df1, function(x) as.numeric(as.character(x)))
    names(df1) <- unlist(strsplit(names(df), split = ".", fixed=TRUE))
    
    > df1
       header   ST adk fumC gyrB icd mdh purA recA
    1       1   10  10   11    4   8   8    8    2
    2       2   48   6   11    4   8   8    8    2
    3       3   58   6    4    4  16  24    8   14
    4       4   88   6    4   12   1  20   12    7
    5       5  117  20   45   41  43   5   32    2
    6       6 7036 526    7    1   1   8   71    6
    7       7  101  43   41   15  18  11    7    6
    8       8 3595 112   11    5  12   8   88   86
    9       9  117  20   45   41  43   5   32    2
    10     10  744  10   11  135   8   8    8    2
    

    数据

    df <-structure(list(header = 1:10, ST.adk.fumC.gyrB.icd.mdh.purA.recA = c(" 10 10 11 4 8 8 8 2", 
                                                                         " 48 6 11 4 8 8 8 2", " 58 6 4 4 16 24 8 14", " 88* 6* 4 12 1 20 12 7", 
                                                                         " 117 20 45 41 43 5 32 2", " 7036 526 7 1 1 8 71 6", " 101 43 41 15 18 11 7 6", 
                                                                         " 3595 112 11 5 12 8 88 86", " 117 20 45 41 43 5 32 2", " 744 10 11 135 8 8 8 2"
    )), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"
    ))
    
        2
  •  0
  •   davsjob    6 年前

    与您的示例几乎相同的解决方案,只需稍作调整。这就是我要做的,假设你想删除 '*' 在栏目中:

    library(tidyverse)
    library(hablar)
    
    # Vector of new column names
    ids <- simplify(strsplit(names(df)[-1], 
                             split = ".", 
                             fixed = T))
    
    # Seperate second column
    df %>%
      mutate_at(2, funs(trimws(gsub("\\*", "", .)))) %>%
      separate(2, into = ids, extra = "merge", sep = " ") %>% 
      retype()
    

    给你:

    # A tibble: 10 x 9
       header    ST   adk  fumC  gyrB   icd   mdh  purA  recA
        <int> <int> <int> <int> <int> <int> <int> <int> <int>
     1      1    10    10    11     4     8     8     8     2
     2      2    48     6    11     4     8     8     8     2
     3      3    58     6     4     4    16    24     8    14
     4      4    88     6     4    12     1    20    12     7
     5      5   117    20    45    41    43     5    32     2
     6      6  7036   526     7     1     1     8    71     6
     7      7   101    43    41    15    18    11     7     6
     8      8  3595   112    11     5    12     8    88    86
     9      9   117    20    45    41    43     5    32     2
    10     10   744    10    11   135     8     8     8     2