#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.6… TRUE
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.5… TRUE
5 2589 3982 "2.75 - 3.15" "2.75… " 3.1… TRUE
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.3… TRUE
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.1… TRUE
10 5211 8334 "6.90 - 7.40" "6.90… " 7.4… TRUE
11 9994 13542 "2.73 - 2.78" "2.73… " 2.7… TRUE
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.7… TRUE
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