Создать идентификатор столбца из строки в R - PullRequest
1 голос
/ 17 марта 2020

У меня ниже фрейма данных:

Ввод:

df <- data.frame(a=c('id','a','b','c','d','id','a','b','c','d','id','a','b','c','d','id','a','b','c','d','id','a','b','c','d'),
          value=c(1,'a1','b1','c1','d1',2,'a2','b2','c2','d2',3,'a3','b3','c3','d3',4,'a4','b4','c4','d4',5,'a5','b5','c5','d5'),
          )

Я хочу создать новый столбец id, и под этим * 1008 должны быть назначены строки ниже первого id *.

Желаемый результат:

output <- data.frame(id=c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5),
                     var=c('a','b','c','d','a','b','c','d','a','b','c','d','a','b','c','d','a','b','c','d'),
                     value=c('a1','b1','c1','d1','a2','b2','c2','d2','a3','b3','c3','d3','a4','b4','c4','d4','a5','b5','c5','d5'))

ПРИМЕЧАНИЕ: Решение также должно работать для таких случаев:

df <- data.frame(a=c('id','a','b','c','d','id','a','b','c','d','id','a','b','c','d','id','a','b','c','d','id','a','b','c','d'),
          value=c('id1','a1','b1','c1','d1','id12','a2','b2','c2','d2','idd3','a3','b3','c3','d3','i44','a4','b4','c4','d4','i15','a5','b5','c5','d5')
          )

expected_output <- data.frame(id=c('id1','id1','id1','id1','id12','id12','id12','id12','idd3','idd3','idd3','idd3','i44','i44','i44','i44','i15','i15','i15','i15'),
                     var=c('a','b','c','d','a','b','c','d','a','b','c','d','a','b','c','d','a','b','c','d'),
                     value=c('a1','b1','c1','d1','a2','b2','c2','d2','a3','b3','c3','d3','a4','b4','c4','d4','a5','b5','c5','d5'))

Ответы [ 3 ]

2 голосов
/ 17 марта 2020

Вот базовое решение R.

df$id <- cumsum(df$a == 'id')
df <- df[df$a != 'id', ]
names(df)[1] <- 'var'
df <- df[c(3, 1, 2)]

Вот решение dplyr.

library(dplyr)

df %>%
  mutate(id = cumsum(a == 'id')) %>%
  filter(a != 'id') %>%
  rename(var = a) %>%
  select(id, var, value)
2 голосов
/ 17 марта 2020

Основываясь на ваших изменениях, я думаю, что это работает:

library(dplyr)
library(tidyr)
df %>%
  mutate(id = ifelse(a == "id", as.character(value), NA)) %>%
  fill(id) %>%
  filter(a != "id")
#    a value   id
# 1  a    a1  id1
# 2  b    b1  id1
# 3  c    c1  id1
# 4  d    d1  id1
# 5  a    a2 id12
# 6  b    b2 id12
# 7  c    c2 id12
# 8  d    d2 id12
# 9  a    a3 idd3
# 10 b    b3 idd3
# 11 c    c3 idd3
# 12 d    d3 idd3
# 13 a    a4  i44
# 14 b    b4  i44
# 15 c    c4  i44
# 16 d    d4  i44
# 17 a    a5  i15
# 18 b    b5  i15
# 19 c    c5  i15
# 20 d    d5  i15

Правило для его генерации c не очень ясно. В первом случае value, соответствующий a == "id", не начинается с буквы «id», и вы хотите добавить его.

Второй случай более запутанный, некоторые значения начинаются с « id ", другие только с" я ", и ничего не добавляется. Я не понимаю, почему «i44» является хорошим идентификатором, как «idd3», но не «1». Мое лучшее предположение состоит в том, что все, что начинается с «i», в порядке, но в противном случае мы вставим «id». Мы можем сделать это простым этапом последующей обработки. Я использую «начинается с 'i'» в качестве критерия, и я оставляю его на ваше усмотрение в соответствии с реальными критериями.

df %>%
  mutate(id = ifelse(a == "id", as.character(value), NA_character_)) %>%
  fill(id) %>%
  filter(a != "id") %>%
  mutate(id = ifelse(grepl("^i", id), id, paste0("id", id)))

Выше соответствует ожидаемый результат для обоих входов.

2 голосов
/ 17 марта 2020

Среди других опций:

library(stringr)
df %>%
  filter(a != "id") %>%
  mutate(id = str_extract(value, "\\d+$"))

Или:

df %>%
  mutate(id = if_else(a == "id", value, factor(NA))) %>%
  fill(id) %>%
  filter(a != "id")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...