Создайте второй список, используя цикл for, проходящий через все элементы первого списка

#r #list #for-loop

#r #Список #цикл for

Вопрос:

Я довольно новичок в R, и я хочу очистить свой код, чтобы он был более динамичным и компактным. По сути, я выполняю два вывода SQL и получаю два фрейма данных «Обращения» и «Должники», оба из которых имеют поле «case_id», которое связывает обращение с должником, и поле «продукт». Я создаю список, который разделяет обращения df по продуктам:

Cases_products <- split(Cases, list(Cases$product))

и получите список, содержащий 4 элемента: product1, product2, product3 и product4. Затем я создаю второй список, который разделяет «Должников» на соответствующие сегменты продуктов, также предоставляя список из 4 элементов:

 Debtors_products <- list(
   "product1" = merge(x = Debtors, y = Cases_products[["product1"]], by = "case_key", all.y = TRUE),
   "product2" = merge(x = Debtors, y = Cases_products[["product2"]], by = "case_key", all.y = TRUE),
   "product3" = merge(x = Debtors, y = Cases_products[["product3"]], by = "case_key", all.y = TRUE), 
   "product4" = merge(x = Debtors, y = Cases_products[["product4"]], by = "case_key", all.y = TRUE))
 

Как вы могли заметить, я хочу, чтобы имена элементов в моем втором списке были такими же, как и в первом списке, с которым я могу присоединиться / подключиться.

Я чувствую, что второй список «Debtors_products» должен быть заменен циклом for, увы, мои попытки были тщетными. Я считаю, что мой приведенный ниже код иллюстрирует, как я хочу сделать свой код более компактным и динамичным, но он не работает.

 for (i in seq_along(Cases_product))

{Debtors_products <- list(Cases_product[i] = merge(x = Debtors, y = Cases_product[[i]], by = "case_key", all.y = TRUE))}
 

Любая помощь будет оценена.

/С уважением

Комментарии:

1. Приготовьтесь нанести удар по голове … не удается проиндексировать LHS операции присваивания.

Ответ №1:

Во время присваивания внутри цикла индексируйте элемент с желаемым значением без list , чтобы избежать вложенной структуры.

 # INITIZALIZE NAMED LIST
Debtors_products <- setNames(vector(mode="list", length=length(Cases_product)),
                             paste0("product", seq_along(Cases_product)))

# ITERATIVELY ASSIGN BY INDEX
for (i in seq_along(Cases_product)) {
   Debtors_products[[i]] <- merge(x=Debtors, y=Cases_product[[i]],
                                  by="case_key", all.y=TRUE))
} 
 

Однако используйте apply family, чтобы избежать учета присвоения и индексации. В частности, используйте lapply вместо for цикла:

 Debtors_products <- lapply(Cases_products, function(df)
         merge(x=Debtors, y=df, by="case_key", all.y=TRUE)
)
 

Еще лучше, поскольку вы используете split lapply , оптимизируйте оба вызова с помощью редко используемой by (объектно-ориентированной оболочки для tapply ):

 Debtors_products <- by(Cases, Cases$product, FUN=function(df)
         merge(x=Debtors, y=df, by="case_key", all.y=TRUE)
)
 

И в SQL запустите внешнее соединение и импортируйте больший набор и разделите без итеративного merge :

SQL

 SELECT d.*, c.*        -- ADJUST TO AVOID NAME COLLISION
FROM Debtors d
RIGHT JOIN Cases c
  ON c.case_key = d.case_key
 

R

 Debtors_Products <- split(Large_SQL_Result, Large_SQL_Result$product)