#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=", "))