Разделение строки и извлечение информации о десятичных разрядах и минимальных и максимальных значениях с помощью strsplit

#r #dataframe #tidyverse #tidyr #strsplit

#r #фрейм данных #аккуратная вселенная #тидыр #стросплит #tidyverse #tidyr #strsplit

Вопрос:

У меня есть некоторые данные, которые выглядят следующим образом:

      grp  grp2                                            figures
1  10016 13567                                        0.55 - 0.65
2   1270  2090                                           1.90 - 2
3   8757 12259                              6.60 - 7n8.50 - 9.50
4   2589  3982                                        2.75 - 3.15
5   9099 12573 1.24 - 1.30n1.22 - 1.30n0.08 - 0.10n0.10 - 0.12
6   5211  8334                                        6.90 - 7.40
7   9994 13542                                        2.73 - 2.78
8   2685  4113              0.72 - 0.74n2.75 - 2.77n3.10 - 3.18
9   9778 13295            32 - 39n190 - 200n142 - 152n90 - 100
10   772  1317                                        2.20 - 2.40
  

Я хотел бы извлечь некоторую информацию из figures столбца. Я хочу разделить столбцы на min и max , что можно сделать, разделив, - используя что-то вроде strsplit(dat$figures, split = "-") (но я хочу, чтобы это было на два столбца min и max ). Как только у меня это будет, я хотел бы добавить новый столбец, который дает мне 0 или 1 , содержит ли наблюдение десятичную дробь или нет. Я хотел бы сделать это построчно, некоторые наблюдения содержат n , поэтому мой ожидаемый результат для следующего наблюдения 1.24 - 1.30n1.22 - 1.30n0.08 - 0.10n0.10 - 0.12 был бы следующим.

 min     max      containsDecimal
1.24    1.30           1
1.22    1.30           1
0.08    0.10           1
0.10    0.12           1
  

Следующий 32 - 39n190 - 200n142 - 152n90 - 100 пример будет выглядеть следующим образом:

 min    max       containsDecimal
32     39             0
190    200            0
142    152            0
90     100            0
  

Где сейчас containsDecimal находится 0 колонка. Я пытаюсь добиться того, чтобы результаты содержались внутри ячейки, в которой находится это наблюдение, и разделялись на n , а не расширялись наружу.

Данные:

 dat <- structure(list(grp = c("10016", "1270", "8757", "2589", "9099", 
"5211", "9994", "2685", "9778", "772"), grp2 = c(13567L, 2090L, 
12259L, 3982L, 12573L, 8334L, 13542L, 4113L, 13295L, 1317L), 
    figures = c("0.55 - 0.65", "1.90 - 2", "6.60 - 7n8.50 - 9.50", 
    "2.75 - 3.15", "1.24 - 1.30n1.22 - 1.30n0.08 - 0.10n0.10 - 0.12", 
    "6.90 - 7.40", "2.73 - 2.78", "0.72 - 0.74n2.75 - 2.77n3.10 - 3.18", 
    "32 - 39n190 - 200n142 - 152n90 - 100", "2.20 - 2.40")), class = "data.frame", row.names = c(NA, 
-10L))
  

Ответ №1:

Одним из возможных решений tidyverse было бы

 library(dplyr)
library(tidyr)
library(stringr)

dat %>% 
  mutate(figures = str_split(figures, "n")) %>% 
  unnest_longer(figures) %>% 
  separate(figures, into = c("min", "max"), " - ", convert = TRUE) %>% 
  mutate(contains_decimal = if_else(grepl(".", min, fixed = TRUE) | grepl(".", max, fixed = TRUE), 1, 0))

# A tibble: 19 x 5
   grp    grp2    min    max contains_decimal
   <chr> <int>  <dbl>  <dbl>            <dbl>
 1 10016 13567   0.55   0.65                1
 2 1270   2090   1.9    2                   1
 3 8757  12259   6.6    7                   1
 4 8757  12259   8.5    9.5                 1
 5 2589   3982   2.75   3.15                1
 6 9099  12573   1.24   1.3                 1
 7 9099  12573   1.22   1.3                 1
 8 9099  12573   0.08   0.1                 1
 9 9099  12573   0.1    0.12                1
10 5211   8334   6.9    7.4                 1
11 9994  13542   2.73   2.78                1
12 2685   4113   0.72   0.74                1
13 2685   4113   2.75   2.77                1
14 2685   4113   3.1    3.18                1
15 9778  13295  32     39                   0
16 9778  13295 190    200                   0
17 9778  13295 142    152                   0
18 9778  13295  90    100                   0
19 772    1317   2.2    2.4                 1
  

Комментарии:

1. Я думаю, что это почти дает то, что я хочу, но это почти удваивает размер набора данных, есть ли способ сохранить набор данных того же размера и сохранить формат, т. Е. Разделенный на n .

2. Итак, вы хотите получить несколько столбцов min / max, по одному для каждой пары чисел, разделенных n ? Каким будет ожидаемый результат для строки, подобной 32 - 39n190 - 200n142 - 152n90 - 100 ?

3. Да, поскольку данные в настоящее время находятся в figures столбце (где каждое наблюдение / строка разделены n новой строкой — я бы хотел, чтобы выходные данные были такими же, как эти (каждый результат разделен новой строкой n .

4. Извините, но мне пока не ясно. Было бы лучше, если бы вы отредактировали свой вопрос с ожидаемым результатом выборки набора данных dat (пожалуйста, будьте конкретны)

Ответ №2:

 library(tidyverse)

dat <- mutate(dat, figs = stringr::str_split(figures, "n")) # produces a list column. In the other words, some of the rows of `figs`  column have more than one element. 
dat <- unnest(dat, col = figs)
dat <- separate(dat, figs,c("min", "max"), "-") # you could use convert = TRUE, to convert min and max into numeric. 
dat <- mutate(dat, contains_decimal = grepl("\.", min) amp; grepl("\.", max)) # since type of min and max are characters, containing decimal mean containing literally a period. 
  
 # A tibble: 19 x 6
   grp    grp2 figures                            min    max    contains_decimal
   <chr> <int> <chr>                              <chr>  <chr>  <lgl>           
 1 10016 13567 "0.55 - 0.65"                      "0.55… " 0.6TRUE            
 2 1270   2090 "1.90 - 2"                         "1.90… " 2"   FALSE           
 3 8757  12259 "6.60 - 7n8.50 - 9.50"            "6.60… " 7"   FALSE           
 4 8757  12259 "6.60 - 7n8.50 - 9.50"            "8.50… " 9.5TRUE            
 5 2589   3982 "2.75 - 3.15"                      "2.75… " 3.1TRUE            
 6 9099  12573 "1.24 - 1.30n1.22 - 1.30n0.08 -… "1.24… " 1.3… TRUE            
 7 9099  12573 "1.24 - 1.30n1.22 - 1.30n0.08 -"1.22… " 1.3TRUE            
 8 9099  12573 "1.24 - 1.30n1.22 - 1.30n0.08 -… "0.08… " 0.1… TRUE            
 9 9099  12573 "1.24 - 1.30n1.22 - 1.30n0.08 -"0.10… " 0.1TRUE            
10 5211   8334 "6.90 - 7.40"                      "6.90… " 7.4TRUE            
11 9994  13542 "2.73 - 2.78"                      "2.73… " 2.7TRUE            
12 2685   4113 "0.72 - 0.74n2.75 - 2.77n3.10 -… "0.72… " 0.7… TRUE            
13 2685   4113 "0.72 - 0.74n2.75 - 2.77n3.10 -"2.75… " 2.7TRUE            
14 2685   4113 "0.72 - 0.74n2.75 - 2.77n3.10 -… "3.10… " 3.1… TRUE            
15 9778  13295 "32 - 39n190 - 200n142 - 152n9… "32 "  " 39"  FALSE           
16 9778  13295 "32 - 39n190 - 200n142 - 152n9… "190 " " 200" FALSE           
17 9778  13295 "32 - 39n190 - 200n142 - 152n9… "142 " " 152" FALSE           
18 9778  13295 "32 - 39n190 - 200n142 - 152n9… "90 "  " 100" FALSE           
19 772    1317 "2.20 - 2.40"                      "2.20… " 2.4… TRUE