Кумулятивно вставьте (объедините) значения, сгруппированные по другой переменной
2289 просмотра
5 ответа
У меня проблема с фреймом данных в R. Я хотел бы вставить содержимое ячеек в разных строках вместе на основе значений ячеек в другом столбце. Моя проблема в том, что я хочу, чтобы вывод выводился постепенно (накопительно). Выходной вектор должен иметь ту же длину, что и входной вектор. Вот таблица сэмпла, похожая на ту, с которой я имею дело:
id <- c("a", "a", "a", "b", "b", "b")
content <- c("A", "B", "A", "B", "C", "B")
(testdf <- data.frame(id, content, stringsAsFactors=FALSE))
# id content
#1 a A
#2 a B
#3 a A
#4 b B
#5 b C
#6 b B
И я хочу, чтобы результат выглядел так:
result <- c("A", "A B", "A B A", "B", "B C", "B C B")
result
#[1] "A" "A B" "A B A" "B" "B C" "B C B"
Что мне НЕ нужно что-то вроде этого:
ddply(testdf, .(id), summarize, content_concatenated = paste(content, collapse = " "))
# id content_concatenated
#1 a A B A
#2 b B C B
Автор: user3860074
Источник
Размещён: 12.11.2019 09:39
Ответы (5)
29 плюса
Вы можете определить функцию «накопительной вставки», используя Reduce
:
cumpaste = function(x, .sep = " ")
Reduce(function(x1, x2) paste(x1, x2, sep = .sep), x, accumulate = TRUE)
cumpaste(letters[1:3], "; ")
#[1] "a" "a; b" "a; b; c"
Reduce
Цикл избегает повторной конкатенации элементов с самого начала, так как он удлиняет предыдущую конкатенацию следующим элементом.
Применяя его по группам:
ave(as.character(testdf$content), testdf$id, FUN = cumpaste)
#[1] "A" "A B" "A B A" "B" "B C" "B C B"
Другая идея, может объединить весь вектор в начале и затем постепенно substring
:
cumpaste2 = function(x, .sep = " ")
{
concat = paste(x, collapse = .sep)
substring(concat, 1L, cumsum(c(nchar(x[[1L]]), nchar(x[-1L]) + nchar(.sep))))
}
cumpaste2(letters[1:3], " ;@-")
#[1] "a" "a ;@-b" "a ;@-b ;@-c"
Кажется, это тоже немного быстрее:
set.seed(077)
X = replicate(1e3, paste(sample(letters, sample(0:5, 1), TRUE), collapse = ""))
identical(cumpaste(X, " --- "), cumpaste2(X, " --- "))
#[1] TRUE
microbenchmark::microbenchmark(cumpaste(X, " --- "), cumpaste2(X, " --- "), times = 30)
#Unit: milliseconds
# expr min lq mean median uq max neval cld
# cumpaste(X, " --- ") 21.19967 21.82295 26.47899 24.83196 30.34068 39.86275 30 b
# cumpaste2(X, " --- ") 14.41291 14.92378 16.87865 16.03339 18.56703 23.22958 30 a
... что делает его cumpaste_faster
.
2 плюса
Вот ddply
метод, использующий sapply
и поднабор для вставки вместе:
library(plyr)
ddply(testdf, .(id), mutate, content_concatenated = sapply(seq_along(content), function(x) paste(content[seq(x)], collapse = " ")))
id content content_concatenated
1 a A A
2 a B A B
3 a A A B A
4 b B B
5 b C B C
6 b B B C B
Автор: James
Размещён: 21.07.2014 10:50
2 плюса
data.table
решение
library(data.table)
setDT(testdf)[, content2 := sapply(seq_len(.N), function(x) paste(content[seq_len(x)], collapse = " ")), by = id]
testdf
## id content content2
## 1: a A A
## 2: a B A B
## 3: a A A B A
## 4: b B B
## 5: b C B C
## 6: b B B C B
Автор: David Arenburg
Размещён: 21.07.2014 11:33
2 плюса
Вы также можете попробовать dplyr
library(dplyr)
res <- testdf%>%
mutate(n=row_number()) %>%
group_by(id) %>%
mutate(n1=n[1L]) %>%
rowwise() %>%
do(data.frame(cont_concat= paste(content[.$n1:.$n],collapse=" "),stringsAsFactors=F))
res$cont_concat
#[1] "A" "A B" "A B A" "B" "B C" "B C B"
Автор: akrun
Размещён: 21.07.2014 05:23
0 плюса
Один из вариантов использования dplyr
и purrr
может быть:
testdf %>%
group_by(id) %>%
transmute(content_concatenated = accumulate(content, ~ paste(.x, .y)))
id content_concatenated
<chr> <chr>
1 a A
2 a A B
3 a A B A
4 b B
5 b B C
6 b B C B
Автор: tmfmnk
Размещён: 02.11.2019 10:22
Вопросы из категории :
- r Как получить доступ к последнему значению в векторе?
- r Пакеты оптимизации для R
- r Есть ли у R такие операторские операции, как Perl qw ()?
- r Библиотека / инструмент для рисования тройных / треугольных графиков
- r Участки без заголовков / надписей в R
- r Расчет скользящей средней
- r Режим Emacs ESS - вкладка для области комментариев
- r Преобразование данных из многих строк во многие столбцы
- r Проверить, содержит ли вектор данный элемент
- r Поиск всех позиций для нескольких элементов в векторе
- dataframe Разница между скобками [] и двойной скобкой [[]] для доступа к элементам списка или кадра данных
- dataframe Уровни коэффициента отбрасывания в заданном кадре данных
- dataframe Как отсортировать фрейм данных по нескольким столбцам
- dataframe Как объединить (объединить) кадры данных (внутренний, внешний, левый, правый)?
- dataframe Фильтрация строк данных.файла по логическому условию
- dataframe Изменение формы data.frame из широкого в длинный формат
- dataframe Как преобразовать столбец фрейма данных в числовой тип?
- dataframe R: Какой самый простой способ распечатать пары значений из data.frame?
- dataframe R: Как записать data.frame, чтобы я мог вставить его в SO, чтобы другие могли его прочитать?