загрузить несколько файлов .dta, выбирая переменные - PullRequest
0 голосов
/ 25 мая 2020

У меня есть несколько файлов Stata, которые я хотел бы прочитать как отдельные фреймы данных, выбирая из каждого c переменные.

Это следующие файлы:

a_hhresp.dta
b_hhresp.dta
c_hhresp.dta
d_hhresp.dta
etc.

Переменные, которые я хочу получить каждый из них:

a_hidp, a_fihhmnnet1_dv, a_ieqmoecd_dv
b_hidp, b_fihhmnnet1_dv, b_ieqmoecd_dv
etc.

Вот что у меня сейчас есть:

hh1 <- read_dta("a_hhresp.dta", col_select=c("a_hidp", "a_fihhmnnet1_dv", "a_ieqmoecd_dv"))
hh2 <- read_dta("b_hhresp.dta", col_select=c("b_hidp", "b_fihhmnnet1_dv", "b_ieqmoecd_dv"))
hh3 <- read_dta("c_hhresp.dta", col_select=c("c_hidp", "c_fihhmnnet1_dv", "c_ieqmoecd_dv"))
hh4 <- read_dta("d_hhresp.dta", col_select=c("d_hidp", "d_fihhmnnet1_dv", "d_ieqmoecd_dv"))
hh5 <- read_dta("e_hhresp.dta", col_select=c("e_hidp", "e_fihhmnnet1_dv", "e_ieqmoecd_dv"))
hh6 <- read_dta("f_hhresp.dta", col_select=c("f_hidp", "f_fihhmnnet1_dv", "f_ieqmoecd_dv"))
hh7 <- read_dta("g_hhresp.dta", col_select=c("g_hidp", "g_fihhmnnet1_dv", "g_ieqmoecd_dv"))
hh8 <- read_dta("h_hhresp.dta", col_select=c("h_hidp", "h_fihhmnnet1_dv", "h_ieqmoecd_dv"))
hh9 <- read_dta("i_hhresp.dta", col_select=c("i_hidp", "i_fihhmnnet1_dv", "i_ieqmoecd_dv"))

Это, конечно, плохая форма, ненужное копирование-вставка - должно быть возможно сделать это с помощью итерации строка или две. И если я смогу решить, как это сделать для этого компонента, то, возможно, я смогу использовать то, что я узнал, для более эффективного выполнения других задач.

Я имел в виду использовать lapply (предварительно создав список файлов), но я не вижу способа выделить столбцы на начальном этапе.

Я стараюсь избегать написания отдельных строк для таких задач - спасибо за любые предложения.

EDIT

Это большой набор данных панели («Understanding Society» в Великобритании) с 9 волнами (пока) и несколькими файлами на волну. То, что я описал выше, соответствует данным на уровне домашних хозяйств.

После создания списка («listhh») я могу сосчитать:

dfhh <- lapply(listhh, function(x) read_dta(x))

Это работает, но требует всего переменные - значит, список фреймов данных очень велик.

При использовании lapply я не вижу ничего, что работало бы с опцией col_select, потому что префиксы переменных разные для каждого файла.

Я могу загрузить все файлы с помощью lapply (содержащего все переменные), затем я могу превратить его в фрейм данных:

dfhh <- rbindlist(dfhh, fill = TRUE)

И затем я могу выбрать только те столбцы, которые мне нужны:

dfhh %<>% select(grep("([a-z])_hidp", names(dfhh)), grep("([a-z])_fihhmnnet1_dv", names(dfhh)), grep("([a-z])_ieqmoecd_dv", names(dfhh)))

Это работает. Но когда дело доходит до файлов индивидуального уровня, все на намного больше. Когда я пробую тот же подход с отдельными файлами, я получаю «фатальную ошибку» и мне приходится перезапускать R.

Было бы лучше выбрать столбцы при чтении данных ...

ДАЛЬНЕЙШЕЕ РЕДАКТИРОВАНИЕ

Я думаю, что все же лучше читать файлы в отдельные фреймы данных. Мне нужно объединить данные о домохозяйстве с индивидуальными данными, используя ключ c для волны (для волны A ключ: by = "a_hidp"). Если у меня есть один фрейм данных, содержащий все данные домашнего хозяйства, уникального ключа больше не будет - теперь у меня есть a_hidp, b_hidp, c_hidp, et c.) Я думаю, мне нужно 9 отдельных фреймов данных на уровне домашнего хозяйства и 9 соответствующих индивидуальных -уровневые фреймы данных. Слейтесь с волнами, затем присоединитесь к волнам.

Ответы [ 2 ]

0 голосов
/ 27 мая 2020

Я наконец-то понял, как это сделать правильно. Следующий код работает, загружая все соответствующие наборы данных, выбирая нужные мне переменные и извлекая фреймы данных из списка (с присвоением имен элементам списка):

#create list
listhh <- list.files("path", pattern = "*_hhresp.dta")

#read the files
uh <- lapply(listhh, read_dta)

#select variables:
uh <- lapply(uh, function(x) x%>% select(ends_with("_hidp"),
                                         ends_with("_fihhmnnet1_dv"),
                                         ends_with("_ieqmoecd_dv")))

#name the list elements:
names(uh) <- gsub("\\.dta$", "", listhh)

#extract the individual dataframes from the list
list2env(uh, .GlobalEnv)

Спасибо Дэвиду за получение я иду на это.

0 голосов
/ 26 мая 2020

Не зная слишком много о ваших данных / входных данных (возможно, вы можете предоставить дополнительный контекст, например, ваш lapply код), обычно я бы решил такие проблемы, как это

library(tidyverse)

files <- list.files("some-path", pattern = "*.dta$", full.name = TRUE)

all_data <- map_dfr(files, read_dta)

map_dfr похож на вызов lapply, но возвращает data.frame (df), который состоит из привязок строк (r в dfr).

Edit

lapply или map_* позволяют передавать дополнительные аргументы, т. Е.

foo <- function(times, text) {
  paste(rep(text, times), collapse = ", ")
}

foo(3, "hello")
#> [1] "hello, hello, hello"

# notice: text="val" given in lapply
lapply(1:3, foo, text = "val")
#> [[1]]
#> [1] "val"
#> 
#> [[2]]
#> [1] "val, val"
#> 
#> [[3]]
#> [1] "val, val, val"

library(purrr)
map_chr(1:3, foo, text = "val")
#> [1] "val"           "val, val"      "val, val, val"

Создано 26 мая 2020 года пакетом REPEX (v0.3.0)

Таким образом, в вашем случае вы можете иметь следующее:

cols <- c("a_hidp", "a_fihhmnnet1_dv", "a_ieqmoecd_dv")

data <- map_dfr(files, read_dta, col_select = cols)

# usually also a good version, which creates a new column with the filename
data <- map(files, read_dta, col_select = cols) %>%
     bind_rows(.id = "file")

Edit 2

Также посмотрите ends_with(). Ваш код выбора можно упростить до

dfhh %>% 
    select(
        ends_with("_hidp",
        ends_with("_fihhmnnet1_dv"),
        ends_with("_ieqmoecd_dv")
    )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...