Список фреймов данных, содержащих индексы строк и столбцов для выбора данных из большего фрейма данных - PullRequest
0 голосов
/ 12 мая 2018

У меня есть список фреймов данных. Один из столбцов содержит имя фрейма данных:

a <- data.frame(PIN = c(1:3), Item = c("a", "a", "a"))
b <- data.frame(PIN = c(4:6), Item = c("b", "b", "b"))
List <- list(a, b)

И большой фрейм данных, из которого я хочу извлечь данные. Значения в первых столбцах в моем списке фреймов данных соответствуют значениям в первом столбце или большем фрейме данных, а имена / значения во вторых столбцах моего списка фреймов данных соответствуют именам столбцов в более крупном фрейме данных :

DF <-data.frame(PIN = c(1:10), a = c(101:110), b = c(201:210), c = c(301:310))

Я хочу добавить столбцы к фреймам данных в моем списке, извлекая данные из DF, используя PIN-код в качестве индекса строки и Item в качестве индекса столбца. По сути, я получу:

a <- data.frame(PIN = c(1:3), Item = c("a", "a", "a"), a = c(101:103))
b <- data.frame(PIN = c(4:6), Item = c("b", "b", "b"), b = c(204:206))
List <- list(a, b)

Как я могу это сделать?

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Вы можете пересмотреть свои структуры данных:

  1. Список одинаково структурированных data.frames может быть объединен в один больший объект данных, который позволяет избежать итерации по элементам списка.
  2. Поскольку столбцы «полезной нагрузки» a, b и c из DF содержат одинаковый тип данных, DF можно преобразовать из широкого в длинный формат. Это преобразует имена столбцов в элементы данных, которые легче использовать для операции поиска.

Итак, мое предложение:

library(data.table)

keys <- rbindlist(List, idcol = TRUE)
DT <- setDT(melt(DF, id.vars = "PIN", variable.name = "Item"))
DT[keys, on = .(PIN, Item)]
   PIN Item value .id
1:   1    a   101   1
2:   2    a   102   1
3:   3    a   103   1
4:   4    b   204   2
5:   5    b   205   2
6:   6    b   206   2

Если вам все еще нужен результат списка:

split(DT[keys, on = .(PIN, Item)], by = ".id")
$`1`
   PIN Item value .id
1:   1    a   101   1
2:   2    a   102   1
3:   3    a   103   1

$`2`
   PIN Item value .id
1:   4    b   204   2
2:   5    b   205   2
3:   6    b   206   2
0 голосов
/ 12 мая 2018

С tidyr, dplyr и purrr мы могли бы сделать:

DF <- tidyr::gather(DF, key = "Item", value, -PIN)

purrr::map(List, dplyr::left_join, DF, by = c("PIN", "Item"))
[[1]]
  PIN Item value
1   1    a   101
2   2    a   102
3   3    a   103

[[2]]
  PIN Item value
1   4    b   204
2   5    b   205
3   6    b   206

Обратите внимание, что вы получите предупреждение, потому что данные примера содержат факторы. Добавьте stringsAsFactors = FALSE при построении фреймов данных, чтобы избежать этого предупреждающего сообщения.

Вы можете заменить функцию purrr map на базовые R lapply, используя:

lapply(List, dplyr::left_join, DF, by = c("PIN", "Item"))

Кроме того, одной из альтернатив решения Уве может быть:

library(tidyverse)

DF <- gather(DF, key = "Item", value, -PIN)

List %>% 
  map(mutate_if, is.factor, as.character) %>% # optional, but solves the warning message by converting factors to character
  map_df(rbind, .id = "id") %>% 
  left_join(DF) %>% 
  split(.$id)
$`1`
  id PIN Item value
1  1   1    a   101
2  1   2    a   102
3  1   3    a   103

$`2`
  id PIN Item value
4  2   4    b   204
5  2   5    b   205
6  2   6    b   206

Данные:

# Create list
List <- list(
  data.frame(PIN = c(1:3), Item = c("a", "a", "a")),
  data.frame(PIN = c(4:6), Item = c("b", "b", "b"))
)

# Create data frame
DF <- data.frame(
  PIN = c(1:10), 
  a = c(101:110), 
  b = c(201:210), 
  c = c(301:310)
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...