#r #list #dataframe #dplyr
#r #Список #фрейм данных #dplyr
Вопрос:
У меня есть объекты data.frame в списке, которые также обрабатываются желаемым образом для дальнейшего процесса. Тем не менее, я намерен использовать его дополнительный набор для каждого заданного условия списка, также я просто набросаю вспомогательную функцию для возможного выполнения этой задачи. Я использовал функцию setdiff из пакетов dplyr, держу пари, это правильный способ сделать это. Но результат оказался не таким, как я ожидал. Я попробовал один из возможных подходов с использованием вспомогательной функции для вложенного списка, но вывод был неправильным, если я изменил параметр (type= c («Bio»,»Tech»)). Есть ли какой-нибудь быстрый подход для получения чистого, хорошо сконструированного вывода, который я ожидал? Как я могу это сделать? Есть идеи?
быстрый воспроизводимый пример:
savedList <- list(
foo_saved = data.frame(v1=c(1,6,16), v2=c(4,12,23), nm=c("a1","a2","a3")),
bar_saved = data.frame(v1=c(7,19,31), v2=c(13,28,43), nm=c("b3","b6","b7")),
cat_saved = data.frame(v1=c(5,21,36), v2=c(11,29,42), nm=c("c2","c4","c9"))
)
dropedList <- list(
foo_droped = data.frame(v1=c(6,25,40), v2=c(12,33,49),nm=c("a2","a5","a8")),
bar_droped = data.frame(v1=c(15,19,47), v2=c(18,28,55),nm=c("b4","b6","b9")),
cat_droped = data.frame(v1=c(13,21,36,53), v2=c(19,29,42,67),nm=c("c3","c4","c9","c12"))
)
Я использовал этот трюк для манипулирования списком:
x <- c(savedList, dropedList)
newList <- split(x, sub("_.*", "", names(x)))[sub("_.*", "", names(savedList))]
Это вспомогательная функция, которую я намерен реализовать:
func <- function(list, type=c("Bio", "Tech")) {
type=match.arg(type)
if(type=="Bio") list[[1]] else setdiff(list[[1]], list[[2]])
}
Я сделал это, чтобы, возможно, добиться моего результата:
res <- Map(func, newList)
но это не сработает, если я задам тип как «Tech», setdiff не сможет вернуть дополнительный набор, который я ожидал. Также сложно изменить тип и получить другой вывод, если я использую Map. Есть ли какой-нибудь эффективный способ получить желаемый результат?
Затем я хочу условно использовать дополнительный набор каждого списка.
желаемый результат, если тип «Био»:
output.Bio <- list(
foo_otp = data.frame(v1=c(1,6,16), v2=c(4,12,23), nm=c("a1","a2","a3")),
bar_otp = data.frame(v1=c(7,19,31), v2=c(13,28,43), nm=c("b3","b6","b7")),
cat_otp = data.frame(v1=c(5,21,36), v2=c(11,29,42), nm=c("c2","c4","c9"))
)
желаемый результат, если тип «Технический» :
output.Tech <- list(
foo_otp = data.frame(v1=c(1,16),v2=c(4,23),nm=c("a1","a3")),
bar_otp = data.frame(v1=c(7,31),v2=c(13,43),nm=c("b3","b7")),
cat_otp = data.frame(v1=c(5),v2=(11),nm="c2")
)
Я не могу понять, что пошло не так в вспомогательной функции. Есть предложения, чтобы убедиться, что вспомогательная функция работает более безопасным способом? Как я могу выполнить эту задачу, чтобы получить желаемый результат более эффективно? Большое спасибо
Ответ №1:
Вы изучаете разницу между data.frame
, что anti_join
dplyr
и делает from . Это даст вам output.Tech
:
Map(anti_join, savedList, dropedList)
#Joining by: c("v1", "v2", "nm")
#Joining by: c("v1", "v2", "nm")
#Joining by: c("v1", "v2", "nm")
#$foo_saved
# v1 v2 nm
#1 16 23 a3
#2 1 4 a1
#$bar_saved
# v1 v2 nm
#1 7 13 b3
#2 31 43 b7
#$cat_saved
# v1 v2 nm
#1 5 11 c2
Если вы хотите включить этот фрагмент кода в свой, просто создайте простую функцию:
func = function(L1, L2, type)
{
if(!type %in% c('Bio','Tech')) stop('Wrong type')
if(type=='Bio') return(L1)
Map(anti_join, L1, L2)
}
#func(savedList, dropedList, 'Tech')
#func(savedList, dropedList, 'Bio')
Комментарии:
1. Каким-либо образом явно выберите параметр type и продолжите решение? Как я могу сделать это решение более совместимым? Я имею в виду, что я устанавливаю тип как «Био» или «Технический» и хочу получить соответствующий вывод.
2. Я обогатил свой ответ, чтобы интегрировать это… несмотря на то, что ваша роль заключалась бы в том, чтобы интегрировать ответ на ваш вопрос в ваш код 🙂
3. Отлично. почему anti_join выдает первые три строки? Как я могу этого избежать? Есть хорошая альтернатива для anti_join?
4. потому что мы не упоминаем параметр
by
, и он по умолчанию принимает все имена столбцов фрейма данных (что вам и нужно). Да, есть альтернатива с использованием пакета data.table.