#r #dataframe #dplyr
#r #фрейм данных #dplyr
Вопрос:
У меня есть character vector
и хочу выполнить итерацию по некоторым dataframes
, рассмотреть совпадающие символы и отметить соответствующие значения и, наконец, взять среднее значение всех значений и сохранить результаты в новом dataframe
.
Ниже приведен пример примера:
ip <- c("John", "Amanda", "Aaron", "Peter", "Jolie")
dfs <- data.frame("names" = c('John','Peter','jucy'), "value1" = c(21, 24, 26), "value2" = c(20, 23, 32))
dfg <- data.frame("names" = c('Justin','John','Jill'), "value1" = c(35, 11, 10), "value2" = c(10, 28, 27))
dft <- data.frame("names" = c('Louis','Chan','John'), "value1" = c(42, 74, 26), "value2" = c(26, 53, 54))
dfr <- data.frame("names" = c('Ale','Terry','Tom'), "value1" = c(61, 34, 76), "value2" = c(28, 63, 38))
dfm <- data.frame("names" = c('Sam','Jolie','Peter'), "value1" = c(11, 84, 86), "value2" = c(50, 13, 68))
Ожидаемый результат:
names value1 value2
John 19.33 34
Peter 55 45.5
Jolie 84 13
Для Джона value1 = mean(c(21, 11, 26)) = 19.33
и value2 = mean(c(20, 28, 54)) = 34
Аналогично, для Питера value1 = mean(c(24, 86)) = 55
и value2 = mean(c(23,68)) = 45.5
Ответ №1:
Мы можем получить наборы данных в list
с mget
помощью, связать их вместе с bind_rows
, сгруппировать по mean
library(dplyr)
out <- mget(ls(pattern= '^df[sgtrms]$')) %>%
bind_rows %>%
group_by(names) %>%
summarise(across(everything(), mean, na.rm = TRUE))
out
# A tibble: 12 x 3
# names value1 value2
# <chr> <dbl> <dbl>
# 1 Ale 61 28
# 2 Chan 74 53
# 3 Jill 10 27
# 4 John 19.3 34
# 5 Jolie 84 13
# 6 jucy 26 32
# 7 Justin 35 10
# 8 Louis 42 26
# 9 Peter 55 45.5
#10 Sam 11 50
#11 Terry 34 63
#12 Tom 76 38
Если нам нужно filter
на основе ip
mget(ls(pattern= '^df[sgtrms]$')) %>%
bind_rows %>%
filter(names %in% ip) %>%
group_by(names) %>%
summarise(across(everything(), mean, na.rm = TRUE))
# A tibble: 3 x 3
# names value1 value2
# <chr> <dbl> <dbl>
#1 John 19.3 34
#2 Jolie 84 13
#3 Peter 55 45.5
Или с помощью base R
с aggregate
aggregate(.~ names, subset(do.call(rbind,
mget(ls(pattern = "^df[sgtrms]$"))), names %in% ip), mean)
Ответ №2:
Другим base R
подходом было бы привязать все ваши фреймы данных, применить фильтр на основе ip
вектора и, наконец, объединить с mean()
:
#Vector
ip <- c("John", "Amanda", "Aaron", "Peter", "Jolie")
#Data
dfs <- data.frame("names" = c('John','Peter','jucy'),
"value1" = c(21, 24, 26), "value2" = c(20, 23, 32),stringsAsFactors = F)
dfg <- data.frame("names" = c('Justin','John','Jill'),
"value1" = c(35, 11, 10), "value2" = c(10, 28, 27),stringsAsFactors = F)
dft <- data.frame("names" = c('Louis','Chan','John'),
"value1" = c(42, 74, 26), "value2" = c(26, 53, 54),stringsAsFactors = F)
dfr <- data.frame("names" = c('Ale','Terry','Tom'),
"value1" = c(61, 34, 76), "value2" = c(28, 63, 38),stringsAsFactors = F)
dfm <- data.frame("names" = c('Sam','Jolie','Peter'),
"value1" = c(11, 84, 86), "value2" = c(50, 13, 68),stringsAsFactors = F)
#Bind all
dfmacro <- rbind(dfs,dfg,dft,dfr,dfm)
#Filter based on ip
dfmacro2 <- dfmacro[dfmacro$names %in% ip,]
#Aggregate
aggregate(cbind(value1,value2)~names,data=dfmacro2,mean)
Вывод:
names value1 value2
1 John 19.33333 34.0
2 Jolie 84.00000 13.0
3 Peter 55.00000 45.5
Ответ №3:
Для полноты картины вот два варианта, которые используют data.table
.
OP запросил выполнить итерацию по фреймам данных, извлечь нужные строки путем сопоставления имен и вычислить среднее значение значений для каждого имени во всех извлеченных строках.
Все опубликованные до сих пор ответы предполагают другой порядок операций, который сначала объединяет фреймы данных, затем извлекает нужные строки и, наконец, агрегирует по имени.
Два варианта, предложенные в этом ответе, используют один и тот же маршрут.
library(data.table)
rbindlist(list(dfs, dfg, dft, dfr, dfm))[
names %chin% ip, lapply(.SD, mean), keyby = names]
names value1 value2
1: John 19.33333 34.0
2: Jolie 84.00000 13.0
3: Peter 55.00000 45.5
rbindlist()
объединяет все строки, names %chin% ip
выбирает нужные строки, lapply(.SD, mean)
вычисляет среднее значение по всем столбцам, кроме names
столбца, который используется для группировки.
Альтернативный подход агрегируется в объединении:
library(data.table)
rbindlist(list(dfs, dfg, dft, dfr, dfm))[
.(ip), on = .(names = V1), nomatch = NULL, lapply(.SD, mean), keyby = .EACHI]
Здесь объединенные строки объединяются с ip
, не совпадающие строки игнорируются. В рамках объединения данные группируются и агрегируются одновременно.