Любой способ облегчить вывод при манипулировании данными. кадр в списке?

#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.