【问题标题】:Is there a simple way to use a Stata .do script to import fixed width data into R?有没有一种简单的方法可以使用 Stata .do 脚本将固定宽度的数据导入 R?
【发布时间】:2019-02-26 20:38:10
【问题描述】:

我有一个 Stata .do 脚本文件,用于从固定宽度的 TXT 文件导入数据。 .do 文件如下所示:

#delimit ;

**************************************************************************
   Label           : CDS 2014 ID Map
   Rows            : 4353
   Columns         : 7
   ASCII File Date : December 11, 2017
*************************************************************************;


infix 
      CHLDID14        1 - 5         CHLDSN14        6 - 7         PCGID14         8 - 12   
      PCGSN14        13 - 14        CDSHID14       15 - 18        CHLDINST14     19 - 20   
      PCGINST14      21 - 22   
using [path]\IDMAP14.txt, clear 
;
label variable  CHLDID14     "CHILD 2013 PSID FAMILY IW (ID) NUMBER" ;           
label variable  CHLDSN14     "CHILD 2013 INDIVIDUAL SEQUENCE NUMBER" ;           
label variable  PCGID14      "PCG 2013 PSID FAMILY IW (ID) NUMBER" ;             
label variable  PCGSN14      "PCG 2013 INDIVIDUAL SEQUENCE NUMBER" ;             
label variable  CDSHID14     "CDS 2014 HOUSEHOLD INTERVIEW NUMBER" ;             
label variable  CHLDINST14   "CDS 2014 HH ROSTER CHILD SEQUENCE NUM" ;           
label variable  PCGINST14    "CDS 2014 HH ROSTER PCG SEQUENCE NUM" ;             

有没有一种快速的方法可以使用这个 .do 文件将数据自动导入 R?还是我必须使用列范围手动调整脚本?

我问是因为我只能访问 R(而不是 Stata),但 Stata .do 文件似乎是将数据正确导入 R 的最简单快捷方式。

谢谢!

文件链接:Fixed-width text fileStata .do script

【问题讨论】:

  • Felipe D.,您是否希望使用此文件更好地推断如何使用 read.fwf 之类的东西更好地读取固定宽度的文件?也就是说,您不想为之前定义的布局重新确定这个?
  • 对不起,如果我的原始问题不够清楚。让我澄清一下:上面的 Stata 脚本有一堆命令,当按顺序执行时,成功地将数据从固定宽度的文本文件读入 Stata 中的可用数据集中。但是我无法访问 Stata - 我只能访问上面的 Stata 脚本文件和 R。所以我想知道是否可以使用一些聪明的 R 函数来读取上面的脚本并成功地从固定导入数据-宽度文本文件直接进入 R,而无需通过 Stata。
  • @r2evans:是的,完全正确。我想找到一种方法来利用 Stata 脚本来帮助使用 read.fwf 在 R 中导入东西。谢谢!

标签: r import cross-platform stata fixed-width


【解决方案1】:

这是一个刺,但由于我们没有可用于验证的文件,因此您只能自己解决。我对这种格式所做的许多假设可能需要验证,即:

  • 我们在文字 infix 和文字 using 的行之间找到列定义
  • 每一列的定义正好是columnname from hyphen to,带有空格(即使是单个字符,这也是somename 5 - 5
  • 文件名紧跟在文字using之后;结尾的逗号后面可能跟有 clear 或其他非逗号字符,而不是文件名的一部分
do2fwf <- function(txt) {

  infix <- grep("^infix\\s*", txt) 
  if (length(infix) != 1L) stop("need exactly one 'infix' line")
  using <- grep("^\\s*using\\b", txt)
  if (length(using) != 1L) stop("need exactly one 'using' line")
  if (using < infix) stop("'infix' must occur before 'using'")

  hdrtxt <- txt[ (infix+1):(using-1) ]
  # "      CHLDID14        1 - 5         CHLDSN14        6 - 7         PCGID14         8 - 12   "

  re <- gregexpr("\\S+", hdrtxt)
  m <- regmatches(hdrtxt, re)
  # [[1]]
  #  [1] "CHLDID14" "1"        "-"        "5"        "CHLDSN14" "6"        "-"        "7"        "PCGID14"  "8"       
  # [11] "-"        "12"      

  if (!all(lengths(m) %% 4 == 0))
    stop("not all variables are the right format of 'name i - j'")
  if (any(lengths(m) == 0)) {
    warning("found empty lines, confusing")
    m <- Filter(length, m)
  }

  # need to convert 4x lists into 1x lists
  m2 <- do.call("c", mapply(split, m, lapply(lengths(m), function(a) (1:a-1) %/% 4)))

  nms <- sapply(m2, `[[`, 1)

  froms <- as.integer(sapply(m2, `[[`, 2))
  tos <- as.integer(sapply(m2, `[[`, 4))
  widths <- tos - froms + 1

  filename <- gsub("^\\s*using\\s*", "", txt[using])
  # this works here, but I don't know if it is generic and rule-following
  filename <- gsub("\\s*,[^,]*$", "", filename)

  list(filename = filename, names = nms, widths = widths)
  # x <- read.fwf(filename, widths=widths, ...) # header=FALSE???
  # colnames(x) <- names
}

如果你使用底部的数据(实际上应该只是txt &lt;- readLines("somefile.do"),你会得到这个:

do2fwf(txt)
# $filename
# [1] "[path]\\IDMAP14.txt"
# $names
#            0            1            2            0            1            2            0 
#   "CHLDID14"   "CHLDSN14"    "PCGID14"    "PCGSN14"   "CDSHID14" "CHLDINST14"  "PCGINST14" 
# $widths
# [1] 5 2 5 2 4 2 2

您可以自己使用(根据 cmets)。我不知道read.fwf 可能需要的标题行或其他参数。祝你好运!


文字:

txt <- readLines(textConnection('**************************************************************************
   Label           : CDS 2014 ID Map
   Rows            : 4353
   Columns         : 7
   ASCII File Date : December 11, 2017
*************************************************************************;


infix 
      CHLDID14        1 - 5         CHLDSN14        6 - 7         PCGID14         8 - 12   
      PCGSN14        13 - 14        CDSHID14       15 - 18        CHLDINST14     19 - 20   
      PCGINST14      21 - 22   
using [path]\\IDMAP14.txt, clear 
;
label variable  CHLDID14     "CHILD 2013 PSID FAMILY IW (ID) NUMBER" ;           
label variable  CHLDSN14     "CHILD 2013 INDIVIDUAL SEQUENCE NUMBER" ;           
label variable  PCGID14      "PCG 2013 PSID FAMILY IW (ID) NUMBER" ;             
label variable  PCGSN14      "PCG 2013 INDIVIDUAL SEQUENCE NUMBER" ;             
label variable  CDSHID14     "CDS 2014 HOUSEHOLD INTERVIEW NUMBER" ;             
label variable  CHLDINST14   "CDS 2014 HH ROSTER CHILD SEQUENCE NUM" ;           
label variable  PCGINST14    "CDS 2014 HH ROSTER PCG SEQUENCE NUM" ;             '))

【讨论】:

  • 非常感谢@r2evans!我现在试试这个,看看它是否有效。我已经链接了原始的 Stata .do 文件以及原始的固定宽度数据!
  • 我只是使用了代码。我需要做一些小改动,以确保一切都排成一行。我还添加了一些修改以确保.do 脚本底部的“标签变量”命令也被使用——我使用Hmisc::label 标记了R 中的列。太棒了,非常感谢!!!
猜你喜欢
  • 2021-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-17
  • 1970-01-01
  • 1970-01-01
  • 2019-03-10
  • 1970-01-01
相关资源
最近更新 更多