【问题标题】:R: Concatenating a string to every column in a row (excluding col 1, variable col length, the string is held in col 1 of each row)R:将字符串连接到一行中的每一列(不包括col 1,可变col长度,字符串保存在每行的col 1中)
【发布时间】:2021-06-05 22:38:07
【问题描述】:

我有一个包含多行/多行的制表符分隔文件,每行包含可变数量的列:

Name1 String111 String112 NA        NA
Name2 String121 String122 String123 NA
Name3 String131 String132 String133 String134

等等等等(没有关于哪一行有多少条目的模式)。我想将第一列中的名称添加到该行/行中每个占用 (!= NA) 列的开头,以便我最终得到:

Name1 Name1String111 Name1String112 NA             NA
Name2 Name2String121 Name2String122 Name2String123 NA
Name3 Name3String131 Name3String132 Name3String133 Name3String134

我的尝试我的容量限制是更改所有行中单个列的值:

Table$X2 <- paste(Table$X1, Table$X2)

然后我开始为所有专栏工作:

NewTable <- lapply(2:nrow(Table), 
function (x) get(paste0("Table$X", x )) <-  paste(Table$X1, " ", get(paste0("Table$X", x )))
)

最后,我的目标是创建一个 /n 分隔的与一组名称关联的变量列表。

例如,如果我想要 (Name1, Name2) 最后我会:

Name1String111 
Name1String112
Name2String121 
Name2String122 
Name2String123

我的计划是使用我从这个问题创建的表删除第一列,然后将所有剩余的列转换为行。

【问题讨论】:

    标签: r dataframe concatenation apply lapply


    【解决方案1】:

    使用lapply 遍历每一列并将V1 列粘贴到它们。

    df[-1] <- lapply(df[-1], function(x) stringr::str_c(df$V1, x))
    df
    #     V1             V2             V3             V4             V5
    #1 Name1 Name1String111 Name1String112           <NA>           <NA>
    #2 Name2 Name2String121 Name2String122 Name2String123           <NA>
    #3 Name3 Name3String131 Name3String132 Name3String133 Name3String134
    

    数据

    df <- structure(list(V1 = c("Name1", "Name2", "Name3"), V2 = c("String111", 
    "String121", "String131"), V3 = c("String112", "String122", "String132"
    ), V4 = c(NA, "String123", "String133"), V5 = c(NA, NA, "String134")), 
    class = "data.frame", row.names = c(NA, -3L))
    

    【讨论】:

    • 等一下,在 apply 函数中,列是如何存储/定位在 x 中的?有人可以解释一下吗?顺便说一句,也许@Ronak Shah 非常感谢你
    • 我希望 x 传递所有行或所有列,但它如何逐列传递每一行
    • lapply 按列工作。它适用于给定时间的完整列。因此,对于第一次迭代,它是第 2 列,然后是第 3 列,依此类推,直到最后一列。我使用-1 忽略第一列@SkyScraper
    【解决方案2】:

    您可以结合tidyverse 的功能来实现这一点。每一步都将通过管道进入下一个。

    1. 定义数据并加载tidyverse
    library(tidyverse)
    
    my_data <-
      structure(
        list(
          col1 = c("Name1", "Name2", "Name3"),
          col2 = c("String111", "String121", "String131"),
          col3 = c("String112", "String122", "String132"),
          col4 = c(NA, "String123", "String133"),
          col5 = c(NA, NA, "String134")
        ),
        row.names = c(NA, -3L),
        class = c("tbl_df", "tbl", "data.frame")
      )
    
    my_data
    #> # A tibble: 3 x 5
    #>   col1  col2      col3      col4      col5     
    #>   <chr> <chr>     <chr>     <chr>     <chr>    
    #> 1 Name1 String111 String112 <NA>      <NA>     
    #> 2 Name2 String121 String122 String123 <NA>     
    #> 3 Name3 String131 String132 String133 String134
    
    1. mutate() 除第一列外的所有列。该函数将第一列粘贴到每个值,NAs 除外。
    my_data %>% 
      mutate(across(-col1, ~if_else(!is.na(.x), paste0(col1, .x), .x)))
    #> # A tibble: 3 x 5
    #>   col1  col2           col3           col4           col5          
    #>   <chr> <chr>          <chr>          <chr>          <chr>         
    #> 1 Name1 Name1String111 Name1String112 <NA>           <NA>          
    #> 2 Name2 Name2String121 Name2String122 Name2String123 <NA>          
    #> 3 Name3 Name3String131 Name3String132 Name3String133 Name3String134
    
    1. 去掉第一列
    my_data %>% 
      mutate(across(-col1, ~if_else(!is.na(.x), paste0(col1, .x), .x))) %>% 
      select(-col1)
    #> # A tibble: 3 x 4
    #>   col2           col3           col4           col5          
    #>   <chr>          <chr>          <chr>          <chr>         
    #> 1 Name1String111 Name1String112 <NA>           <NA>          
    #> 2 Name2String121 Name2String122 Name2String123 <NA>          
    #> 3 Name3String131 Name3String132 Name3String133 Name3String134
    
    1. 转置或透视较长格式的数据,因此每个观察都有自己的行。请注意,这还会生成一个列,指示前一列的名称。您可以使用values_drop_na = TRUE 摆脱NAs。
    my_data %>% 
      mutate(across(-col1, ~if_else(!is.na(.x), paste0(col1, .x), .x))) %>% 
      select(-col1) %>% 
      pivot_longer(everything(), names_to = "column", values_to = "string", values_drop_na = TRUE)
    #> # A tibble: 9 x 2
    #>   column string        
    #>   <chr>  <chr>         
    #> 1 col2   Name1String111
    #> 2 col3   Name1String112
    #> 3 col2   Name2String121
    #> 4 col3   Name2String122
    #> 5 col4   Name2String123
    #> 6 col2   Name3String131
    #> 7 col3   Name3String132
    #> 8 col4   Name3String133
    #> 9 col5   Name3String134
    
    1. 去掉column 列。
    my_data %>% 
      mutate(across(-col1, ~if_else(!is.na(.x), paste0(col1, .x), .x))) %>% 
      select(-col1) %>% 
      pivot_longer(everything(), names_to = "column", values_to = "string", values_drop_na = TRUE) %>% 
      select(-column)
    #> # A tibble: 9 x 1
    #>   string        
    #>   <chr>         
    #> 1 Name1String111
    #> 2 Name1String112
    #> 3 Name2String121
    #> 4 Name2String122
    #> 5 Name2String123
    #> 6 Name3String131
    #> 7 Name3String132
    #> 8 Name3String133
    #> 9 Name3String134
    

    最后,为结果指定一个名称,以便您可以按照自己的方式存储它。

    result <- my_data %>% 
      mutate(across(-col1, ~if_else(!is.na(.x), paste0(col1, .x), .x))) %>% 
      select(-col1) %>% 
      pivot_longer(everything(), names_to = "column", values_to = "string", values_drop_na = TRUE) %>% 
      select(-column)
    

    reprex package (v1.0.0) 于 2021-03-07 创建

    【讨论】:

    • if_else 中你为什么用~ 谓词?
    • 你使用的.x是什么?
    • 其他一切都有意义!就这么多了!
    • 在该示例中,across() 采用 2 个参数。第一个是列的选择,-col1 我要的是除第一个之外的所有列。第二个参数是一个应用于所有选定列的函数,它可以具有 purrr 样式 lambda 函数的形式,其中~.x +1function(x) x +1 相同。更多详情请查看across()s documentation
    • 谢谢!第一次听说 purrr 风格的 lambda 函数,所以我有很多东西要学!
    【解决方案3】:

    在不是 V1 的列之间进行变异,并将 V1 连接到当前列中的值。

    text="Name1 String111 String112 NA        NA
    Name2 String121 String122 String123 NA
    Name3 String131 String132 String133 String134"
    
    df=read.table(text=text, stringsAsFactors = FALSE)
    library(dplyr)
    library(stringr)
    mutate(df, across(-V1, ~str_c(V1, .)))
    
         V1             V2             V3             V4             V5
    1 Name1 Name1String111 Name1String112           <NA>           <NA>
    2 Name2 Name2String121 Name2String122 Name2String123           <NA>
    3 Name3 Name3String131 Name3String132 Name3String133 Name3String134
    

    【讨论】:

      猜你喜欢
      • 2021-05-19
      • 1970-01-01
      • 2014-08-02
      • 1970-01-01
      • 2017-11-23
      • 1970-01-01
      • 2019-10-11
      • 2020-08-14
      • 1970-01-01
      相关资源
      最近更新 更多