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