【问题标题】:load multiple .dta files selecting variables加载多个 .dta 文件选择变量
【发布时间】:2020-05-25 10:38:44
【问题描述】:

我有多个 Stata 文件,我想将其作为单独的数据帧读取,并从每个文件中选择特定的变量。

文件是:

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(首先创建了一个文件列表)——但我看不到在初始阶段选择列的方法。

我试图避免为此类任务编写单独的行——感谢您的任何建议。

编辑

这是一个大型面板数据集(英国的“理解社会”),包含 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。

读入数据时最好选择列...

进一步编辑

我认为将文件读入单独的数据帧会更好。我必须使用特定于波形的键(对于波形 A,键是:by="a_hidp")将家庭数据与个人数据合并。如果我有一个包含所有家庭数据的数据框,则不再有唯一键——我现在有 a_hidp、b_hidp、c_hidp 等)我想我需要 9 个单独的家庭级数据框和 9 个相应的个人级数据框.在波浪中融合,然后加入波浪。

【问题讨论】:

    标签: r loops dataframe iteration


    【解决方案1】:

    在不太了解您的数据/输入的情况下(也许您可以提供更多上下文,例如您的 lapply 代码),通常我会像这样解决这类问题

    library(tidyverse)
    
    files <- list.files("some-path", pattern = "*.dta$", full.name = TRUE)
    
    all_data <- map_dfr(files, read_dta)
    

    map_dfr 类似于lapply 调用,但返回由行绑定(dfr 中的r)组成的data.frame (df)。

    编辑

    lapplymap_* 允许传递额外的参数,即,

    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"
    

    reprex package (v0.3.0) 于 2020 年 5 月 26 日创建

    所以在你的情况下,你可以有以下几点:

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

    编辑 2

    另外,看看ends_with()。您的选择代码可以简化为

    dfhh %>% 
        select(
            ends_with("_hidp",
            ends_with("_fihhmnnet1_dv"),
            ends_with("_ieqmoecd_dv")
        )
    

    【讨论】:

    • 再次感谢您。困难在于“cols”列表仅适用于第一波的文件。在文件 a_hhresp.dta 中,变量都具有前缀 a_,如 a_hidp。但是在文件 b_hhresp.dta 中,变量都有前缀 b_,如 b_hidp。这是我一直在努力解决的一个核心方面:如何将通配符与文件名和变量/列名一起使用,以便我可以迭代......
    • 如果有硬编码逻辑,您可以尝试传递不带前缀的变量名,然后在函数中添加前缀,然后根据需要合并数据。
    【解决方案2】:

    我终于想出了如何正确地做到这一点。以下代码有效,加载所有相关数据集,选择我想要的变量并从列表中提取数据框(已为列表的元素分配名称):

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

    感谢大卫让我继续这件事。

    【讨论】:

      猜你喜欢
      • 2017-05-06
      • 1970-01-01
      • 1970-01-01
      • 2017-01-17
      • 2014-02-11
      • 2017-11-14
      • 1970-01-01
      • 2015-11-24
      • 1970-01-01
      相关资源
      最近更新 更多