Как я могу объединить строку с каждым элементом вектора в строке фрейма данных?

#r #dataframe #vector #concatenation

#r #фрейм данных #вектор #конкатенация

Вопрос:

Простите за форматирование; это мой первый вопрос.
У меня есть фрейм данных, в котором одна из переменных является строкой, а другая из переменных — вектором.
Что я хотел бы сделать, это объединить строку с каждым элементом вектора в каждой строке фрейма данных. Строки не обязательно имеют одинаковую длину. Векторы не обязательно имеют одинаковую длину.
В принципе, я пытаюсь получить отсюда:

Фрейм данных: назначения

пользователь задача
'Bill' c(1, 2, 3)
'Jae' c(2, 5, 6, 7, 8, 9, 10)
'Marsha' c(1, 11)
'Sunil' c(1, 4, 11, 12)

Сюда:

пользователь-задача
c('Bill-1', 'Bill-2', 'Bill-3')
c('Jae-2', 'Jae-5', 'Jae-6', 'Jae-7', 'Jae-8', 'Jae-9', 'Jae-10')
c('Marsha-1', 'Marsha-11')
c('Sunil-1', 'Sunil-4', 'Sunil-11', 'Sunil-12')

Я пробовал такие вещи, как использование paste0 для подключения пользователя и задачи, но я думаю, что это просто закончилось этим:

пользователь-задача
Bill c(1, 2, 3)
Jae c(2, 5, 6, 7, 8, 9, 10)
Marsha c(1, 11)
Sunil c(1, 4, 11, 12)

У меня есть код для этого, но я разочаровался, пытаясь включить код в это поле. Так много ошибок! Это похоже на отладку StackOverflow после запуска моей головы в стену отладки R. Я немного повозился с apply опциями, но я все еще слишком новичок, чтобы действительно понять, как это использовать.

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

1. Для вставки блоков кода вы просто используете тройные обратные тики в строке до и в строке после блока кода. Чтобы вставить встроенный код, выделите тики.

Ответ №1:

Не уверен, есть ли у вас функция «c» внутри вашего фрейма данных. Но посмотрите, работает ли это:

 library(dplyr)
library(tidyr)
library(stringr)
df %>% mutate(id = row_number()) %>% mutate(task = str_remove_all(task, '[c\(||)]')) %>% separate_rows(task) %>% 
group_by(id) %>% transmute(usertask = str_c(user,'-',task, collapse = ',')) %>% ungroup() %>% select(-id) %>% distinct
# A tibble: 4 x 1
  usertask                                  
  <chr>                                     
1 Bill-1,Bill-2,Bill-3                      
2 Jae-2,Jae-5,Jae-6,Jae-7,Jae-8,Jae-9,Jae-10
3 Marsha-1,Marsha-11                        
4 Sunil-1,Sunil-4,Sunil-11,Sunil-12  
 

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

1. Спасибо за ответ! Единственная проблема, с которой я сталкиваюсь, — это сообщение об ошибке, 1: Problem with 'mutate()' input 'task'. argument is not an atomic vector; coercing но результат по-прежнему выглядит так, как я искал.

Ответ №2:

Используя apply и paste .

 apply(d, 1, function(x) paste(x[1], unlist(x[2]), sep="-"))
# [[1]]
# [1] "Bill-1" "Bill-2" "Bill-3"
# 
# [[2]]
# [1] "Jae-2"  "Jae-3"  "Jae-4"  "Jae-5"  "Jae-6"  "Jae-7"  "Jae-8" 
# [8] "Jae-9"  "Jae-10"
# 
# [[3]]
# [1] "Marsha-1"  "Marsha-11"
# 
# [[4]]
# [1] "Sunil-1"  "Sunil-4"  "Sunil-11" "Sunil-12"
 

Или, используя do.call .

 apply(d, 1, function(x) do.call(paste0, c(sapply(x, unlist), "-")[c(1, 3, 2)]))
 

Данные

 d <- structure(list(user = c("Bill", "Jae", "Marsha", "Sunil"), task = structure(list(
    1:3, 2:10, c(1, 11), c(1, 4, 11, 12)), class = "AsIs")), class = "data.frame", row.names = c(NA, 
-4L))
 

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

1. Спасибо за ответ! Просто для моего собственного понимания, что c(1, 3, 2) делает этот синтаксис? Это значит, что «-» помещается между другими записями?

2. @Aaron Спасибо за ваш вопрос. Это do.call метод, который может быть полезен для более крупных задач, c(c(1, 3, 2) который объединяет "-" значения строк, сгенерированные apply . do.call вызывает функцию и запрашивает другие аргументы в списке в правильном порядке. Сравните 2^3 и do.call("^", list(2, 3)) , но это выходит за рамки этого вопроса. На самом деле проще использовать стандартный способ для вашей проблемы, см. Обновление .

Ответ №3:

Можно также использовать unnest():

 d %>%
unnest(cols=c(task)) %>%
mutate(user1 = paste0(user,"-",task)) %>%
group_by(user) %>%
summarise(user_task = paste(user1,collapse=", "))