Разделение и создание 2 строк из одной в таблице данных R - PullRequest
1 голос
/ 08 мая 2020

У меня есть такой набор данных (dt) в R:

n       id      val
1       1&&2    10
2       3       20
3       4&&5    30

И я хочу получить

n       id      val
1       1       10
2       2       10
3       3       20
4       4       30
5       5       30

Я знаю, что для разделения идентификаторов мне нужно сделать что-то вроде этого: id_split <- strsplit(dt$id,"&&")

Но как мне создать новые строки с одинаковыми val для идентификаторов, которые изначально были вместе в строке?

Ответы [ 5 ]

2 голосов
/ 08 мая 2020

Вы можете cbind разделить, чтобы получить столбец, который вы cbind снова val (переработка).

res <- do.call(rbind, Map(data.frame, id=lapply(strsplit(dat$id, "&&"), cbind), 
                          val=dat$val))
res <- cbind(n=1:nrow(res), res)
res
#   n id val
# 1 1  1  10
# 2 2  2  10
# 3 3  3  20
# 4 4  4  30
# 5 5  5  30
1 голос
/ 08 мая 2020

tstrplit по id от data.table может выполнить работу

library(data.table)
df <- setDT(df)[,.('id' = tstrsplit(id, "&&")), by = c('n','val')]
df[,'n' := seq(.N)]

df
   n val id
1: 1  10  1
2: 2  10  2
3: 3  20  3
4: 4  30  4
5: 5  30  5
1 голос
/ 08 мая 2020

Решение data.table.

library(data.table)
DT <- fread('n       id      val
1       1&&2    10
2       3       20
3       4&&5    30')


DT[,.(id=unlist(strsplit(id,split ="&&"))),by=.(n,val)][,n:=.I][]
#>    n val id
#> 1: 1  10  1
#> 2: 2  10  2
#> 3: 3  20  3
#> 4: 4  30  4
#> 5: 5  30  5

Создано 08.05.2020 с помощью пакета REPEX (v0.3.0)

Примечание:

Еще одно решение для опровержения - by = 1:nrow(DT). Но вам нужно поэкспериментировать с другими столбцами.

1 голос
/ 08 мая 2020

Если кто-то ищет аккуратное решение,

dt %>%
  separate(id, into = paste0("id", 1:2),sep = "&&") %>% 
  pivot_longer(cols = c(id1,id2), names_to = "id_name", values_to = "id") %>% 
  drop_na(id) %>% 
  select(n, id, val)

выводится как

# A tibble: 5 x 3
      n id      val
  <dbl> <chr> <dbl>
1     1 1        10
2     1 2        10
3     2 3        20
4     3 4        30
5     3 5        30

Edit: Как было предложено @sotos и полностью пропущено мной. решение с одним вкладышем

d %>% separate_rows(id, ,sep = "&&")

дает тот же результат, что и

# A tibble: 5 x 3
      n id      val
  <dbl> <chr> <dbl>
1     1 1        10
2     1 2        10
3     2 3        20
4     3 4        30
5     3 5        30
1 голос
/ 08 мая 2020

Вы можете использовать lengths из разделения id и расширять свои строки. Затем установите n как последовательность длины вашего фрейма данных, то есть

l1 <- strsplit(as.character(df$id), '&&')
res_df <- transform(df[rep(seq_len(nrow(df)), lengths(l1)),], 
                    id = unlist(l1), 
                    n = seq_along(unlist(l1)))

, что дает

    n id val
1   1  1  10
1.1 2  2  10
2   3  3  20
3   4  4  30
3.1 5  5  30

Вы можете удалить rownames с rownames(res_df) <- NULL

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...