将非特定长度的字符串拆分为列

时间:2018-07-31 20:26:11

标签: r string dataframe

我有一列字符串,并且我试图将它们分成几列。我已经在线阅读了一些内容(在底部),但是我认为这是不同的。

stringColumn <- c(
  "50m 26.50 26.50 100m 53.82 27.32",                                     
  NA,                                                                      
  "50m 25.83 25.83 100m 52.99 27.16",                                      
  "25m 12.46 12.46 50m 26.26 13.80 75m 40.02 13.76 100m 53.48 13.46",      
  NA,                                                                      
  "25m 11.72 11.72 50m 25.33 13.61 75m 39.15 13.82 100m 52.55 13.40",      
  "50m 27.20 27.20 100m 56.38 29.18 150m 1:26.39 30.01 200m 1:56.16 29.77")

这会持续一段时间(970K行),并且字符串遵循相同的格式,即NA或(在当前点测量总时间,重复)。因为不相等,所以不能使用regex或str_split。我的目标是获取一个数据框,其中包含测量的列名称(25m,50m,100m等),并带有该点的总时间。

所需的输出:

25m     50m     75m     100m    150m  200m    
NA      26.5    NA      53.82   NA    NA       
NA      NA      NA      NA      NA    NA       
12.46   26.26   40.02   53.48   NA    NA       
NA      NA      NA      NA      NA    NA       
11.72   25.33   39.15   52.55   NA    NA       
NA      27.2    NA      56.38   NA    1:56.16 

2 个答案:

答案 0 :(得分:4)

这是使用tidyverse工具的一种方法。我们可以:

  1. str_split(?=\\d+?m)一起使用,仅在距离之间的标记处分割每个字符串(即,空格后跟一些数字和m);
  2. 放入tibble中,添加一个rowid列,以便我们知道哪些度量来自哪些字符串;
  3. unnest,因此每个度量均在其单独的行上;
  4. separate,因此每个度量,总时间和当前时间都有自己的列,并舍弃当前时间
  5. spread使测量成为列标题。

请注意,这与您的示例输出不太匹配,忽略了列顺序,但我认为它与输入正确对应。

library(tidyverse)

stringColumn = c(
  "50m 26.50 26.50 100m 53.82 27.32",
  NA,
  "50m 25.83 25.83 100m 52.99 27.16",
  "25m 12.46 12.46 50m 26.26 13.80 75m 40.02 13.76 100m 53.48 13.46",
  NA,
  "25m 11.72 11.72 50m 25.33 13.61 75m 39.15 13.82 100m 52.55 13.40",
  "50m 27.20 27.20 100m 56.38 29.18 150m 1:26.39 30.01 200m 1:56.16 29.77"
)

stringColumn %>%
  str_split(" (?=\\d+?m)") %>%
  tibble(strings = .) %>%
  rowid_to_column(var = "stringid") %>%
  unnest(strings) %>%
  separate(strings, c("measurement", "totaltime", "timeatcurrentpoint"), sep = " ") %>%
  select(-timeatcurrentpoint) %>%
  spread(measurement, totaltime)
#> # A tibble: 7 x 8
#>   stringid `100m` `150m`  `200m`  `25m` `50m` `75m` `<NA>`
#>      <int> <chr>  <chr>   <chr>   <chr> <chr> <chr> <chr> 
#> 1        1 53.82  <NA>    <NA>    <NA>  26.50 <NA>  <NA>  
#> 2        2 <NA>   <NA>    <NA>    <NA>  <NA>  <NA>  <NA>  
#> 3        3 52.99  <NA>    <NA>    <NA>  25.83 <NA>  <NA>  
#> 4        4 53.48  <NA>    <NA>    12.46 26.26 40.02 <NA>  
#> 5        5 <NA>   <NA>    <NA>    <NA>  <NA>  <NA>  <NA>  
#> 6        6 52.55  <NA>    <NA>    11.72 25.33 39.15 <NA>  
#> 7        7 56.38  1:26.39 1:56.16 <NA>  27.20 <NA>  <NA>

答案 1 :(得分:3)

我们可以将您的数据更改为表达式并对其求值:

stringColumn2 <-  gsub("\\s*(\\d+m)\\s*","'),`\\1`=c('",stringColumn[!is.na(stringColumn)])
stringColumn3 <-  paste0(gsub("^'),","list(",stringColumn2),"'))")
stringColumn4 <-  gsub("\\s+","','",stringColumn3)
stringColumn5 <- paste0("list(",paste(stringColumn4,collapse=","),")")

library(dplyr)
bind_rows(eval(parse(text=stringColumn5)),.id = "id")
# # A tibble: 10 x 7
#    id    `50m` `100m` `25m` `75m` `150m`  `200m` 
#    <chr> <chr> <chr>  <chr> <chr> <chr>   <chr>  
#  1 1     26.50 53.82  <NA>  <NA>  <NA>    <NA>   
#  2 1     26.50 27.32  <NA>  <NA>  <NA>    <NA>   
#  3 2     25.83 52.99  <NA>  <NA>  <NA>    <NA>   
#  4 2     25.83 27.16  <NA>  <NA>  <NA>    <NA>   
#  5 3     26.26 53.48  12.46 40.02 <NA>    <NA>   
#  6 3     13.80 13.46  12.46 13.76 <NA>    <NA>   
#  7 4     25.33 52.55  11.72 39.15 <NA>    <NA>   
#  8 4     13.61 13.40  11.72 13.82 <NA>    <NA>   
#  9 5     27.20 56.38  <NA>  <NA>  1:26.39 1:56.16
# 10 5     27.20 29.18  <NA>  <NA>  30.01   29.77  

中间步骤:

stringColumn2[1]
# [1] "'),`50m`=c('26.50 26.50'),`100m`=c('53.82 27.32"
stringColumn3[1]
# [1] "list(`50m`=c('26.50 26.50'),`100m`=c('53.82 27.32'))"
stringColumn4[1]
# [1] "list(`50m`=c('26.50','26.50'),`100m`=c('53.82','27.32'))"