R — Как редактировать повторяющиеся записи?

#r

Вопрос:

Я считываю данные из csv-файла. Вот как выглядят мои данные. Есть несколько записей с одним и тем же лейблом/вопросом в разные дни. Я хочу добавить цифры к повторяющимся вопросам.

 UserID Full Name DOB EncounterID Date Type label responses  1 John Smith 1-1-90 13 1-1-21 Intro Check Were you given any info? (null) 1 John Smith 1-1-90 13 1-2-21 Intro Check Were you given any info? no 1 John Smith 1-1-90 13 1-3-21 Intro Check Were you given any info? yes 2 Jane Doe 2-2-80 14 1-6-21 Intro Check Were you given any info? no 2 Jane Doe 2-2-80 14 1-6-21 Care Check By using this service.. no 2 Jane Doe 2-2-80 14 1-6-21 Out Check How satisfied are you? unsat  

Желаемый результат (я хотел бы добавить цифры к повторяющимся вопросам, как вы можете видеть ниже):

 UserID Full Name DOB EncounterID Date Type label responses  1 John Smith 1-1-90 13 1-1-21 Intro Check Were you given any info?1 (null) 1 John Smith 1-1-90 13 1-2-21 Intro Check Were you given any info?2 no 1 John Smith 1-1-90 13 1-3-21 Intro Check Were you given any info?3 yes 2 Jane Doe 2-2-80 14 1-6-21 Intro Check Were you given any info? no 2 Jane Doe 2-2-80 14 1-6-21 Care Check By using this service.. no 2 Jane Doe 2-2-80 14 1-6-21 Out Check How satisfied are you? unsat  

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

1. Пожалуйста , опубликуйте свои примеры данных, используя dput(x) , немного сложно захватить эти данные со встроенными пробелами.

Ответ №1:

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

 library(dplyr) df %>%   group_by(UserID, label) %>%   mutate(newcol = row_number(),   label = if(sum(newcol)> 1) paste0(label,newcol) else label) %>%  ungroup() %>%   select(-newcol)  

Или более прямолинейно, как предлагает r2evans (большое спасибо!):

 library(dplyr) df %>%   group_by(UserID, label) %>%   mutate(label=if (n() > 1) paste0(label,row_number()) else label)  
 UserID Full.Name DOB EncounterID Date Type label responses  <int> <chr> <chr> <int> <chr> <chr> <chr> <chr>  1 1 John Smith 1-1-90 13 1-1-21 Intro Check Were you given any info?1 (null)  2 1 John Smith 1-1-90 13 1-2-21 Intro Check Were you given any info?2 no  3 1 John Smith 1-1-90 13 1-3-21 Intro Check Were you given any info?3 yes  4 2 Jane Doe 2-2-80 14 1-6-21 Intro Check Were you given any info? no  5 2 Jane Doe 2-2-80 14 1-6-21 Care Check By using this service.. no  6 2 Jane Doe 2-2-80 14 1-6-21 Out Check How satisfied are you? unsat   

данные:

 df <- structure(list(UserID = c(1L, 1L, 1L, 2L, 2L, 2L), Full.Name = c("John Smith",  "John Smith", "John Smith", "Jane Doe", "Jane Doe", "Jane Doe" ), DOB = c("1-1-90", "1-1-90", "1-1-90", "2-2-80", "2-2-80",  "2-2-80"), EncounterID = c(13L, 13L, 13L, 14L, 14L, 14L), Date = c("1-1-21",  "1-2-21", "1-3-21", "1-6-21", "1-6-21", "1-6-21"), Type = c("Intro",  "Intro", "Intro", "Intro", "Care", "Out"), label = c("Check Were you given any info?",  "Check Were you given any info?", "Check Were you given any info?",  "Check Were you given any info?", "Check By using this service..",  "Check How satisfied are you?"), responses = c("(null)", "no",  "yes", "no", "no", "unsat")), class = "data.frame", row.names = c(NA,  -6L))  

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

1. Не могли бы вы mutate(label = if(n()> 1) paste0(label,row_number()) else label) ? Группировка является естественным потоком для этих данных, приятно.

2. Великие r2evans. Обновлю свой ответ! Большое спасибо!

3. Спасибо. Однако при использовании второго решения я получаю следующую ошибку Error in UseMethod("group_by") : no applicable method for 'group_by' applied to an object of class "function"

4. @AshS Вы пробовали использовать данные, предоставленные моим ответом? Я не получаю ошибки!

5. Кстати: ошибка ( applied ... "function" ), скорее всего, вызвана тем, что вы дословно перепробовали этот код, не понимая, что мы должны были угадать название ваших данных, поэтому ТарДжа сохранил их в d ata f rame с именем df . Однако это неудачное удобство, поскольку, если ваш объект не назван так, и вы не обновляете ответ, чтобы отразить ваши имена переменных, то df это функция base-R.

Ответ №2:

Попробуй это:

 ave(dat$label, dat[c("UserID", "label")],  FUN = function(z) if (length(z) > 1) seq_along(z) else "") # [1] "1" "2" "3" "" "" ""   

которые могут быть использованы в качестве

 dat$label <- paste0(dat$label,  ave(dat$label, dat[c("UserID", "label")],  FUN = function(z) if (length(z) > 1) seq_along(z) else "") ) # UserID Full.Name DOB EncounterID Date Type label responses # 1 1 John Smith 1-1-90 13 1-1-21 Intro Check Were you given any info?1 (null) # 2 1 John Smith 1-1-90 13 1-2-21 Intro Check Were you given any info?2 no # 3 1 John Smith 1-1-90 13 1-3-21 Intro Check Were you given any info?3 yes # 4 2 Jane Doe 2-2-80 14 1-6-21 Intro Check Were you given any info? no # 5 2 Jane Doe 2-2-80 14 1-6-21 Care Check By using this service.. no # 6 2 Jane Doe 2-2-80 14 1-6-21 Out Check How satisfied are you? unsat  

Данные

 dat <- structure(list(UserID = c(1, 1, 1, 2, 2, 2), Full.Name = c("John Smith", "John Smith", "John Smith", "Jane Doe", "Jane Doe", "Jane Doe"), DOB = c("1-1-90", "1-1-90", "1-1-90", "2-2-80", "2-2-80", "2-2-80"), EncounterID = c(13, 13, 13, 14, 14, 14), Date = c("1-1-21", "1-2-21", "1-3-21", "1-6-21", "1-6-21", "1-6-21"), Type = c("Intro", "Intro", "Intro", "Intro", "Care", "Out"), label = c("Check Were you given any info?", "Check Were you given any info?", "Check Were you given any info?", "Check Were you given any info?", "Check By using this service..", "Check How satisfied are you?"), responses = c("(null)", "no", "yes", "no", "no", "unsat")), row.names = c(NA, -6L), class = "data.frame")