Stata 基于正则表达式从文件夹导入文件

Stata 基于正则表达式从文件夹导入文件,stata,Stata,我正在使用DHS数据,它涉及不同文件夹中具有一致命名的各种数据文件。每个文件夹都包含特定国家/地区和调查年份的数据 我想导入名称由组件“HR”组成的数据集,例如我有ETHR41FL.DTA。“人力资源”部分是一致的,但名称的其他组成部分因国家和调查年份而异。我需要一次处理一个数据集,然后转移到下一个数据集,因此我相信自动搜索会有所帮助 运行下面的命令将提供: dir "*.dta" 42.6M 5/17/07 10:49 ETBR41FL.dta 19.4M 7/

我正在使用DHS数据,它涉及不同文件夹中具有一致命名的各种数据文件。每个文件夹都包含特定国家/地区和调查年份的数据

我想导入名称由组件“HR”组成的数据集,例如我有
ETHR41FL.DTA
。“人力资源”部分是一致的,但名称的其他组成部分因国家和调查年份而异。我需要一次处理一个数据集,然后转移到下一个数据集,因此我相信自动搜索会有所帮助

运行下面的命令将提供:

dir "*.dta"

  42.6M   5/17/07 10:49  ETBR41FL.dta      
  19.4M   7/17/06 12:32  ETHR41FL.DTA      
  60.5M   7/17/06 12:33  ETIR41FL.DTA      
  10.6M   7/17/06 12:33  ETKR41FL.DTA      
 234.4k   4/05/07 12:36  ETWI41FL.DTA    
我曾尝试过以下方法,但没有达到预期效果,可能不是最好或最直接的方法:

local datafiles : dir . files  "*.dta" //store file names in a macro
di `datafiles'
etbr41fl.dtaethr41fl.dtaetir41fl.dtaetkr41fl.dtaetwi41fl.dta
我认为下一步是将上面的宏
数据文件
的值存储到一个变量中(因为
strupper
似乎不适用于宏,而适用于变量),然后转换为大写并提取字符串
ETHR41FL.dta
。但是,我在执行此操作时遇到了一个问题:

local datafiles : dir . files  "*.dta" //store file names in a macro

gen datafiles= `datafiles'
invalid '"ethr41fl.dta' 
如果我尝试下面的命令,它会工作,但会给出一个空值变量:

local datafiles : dir . files  "*.dta" //store file names in a macro

gen datafiles= "`datafiles'"
如何将
数据文件的组件存储到新变量中

如果可行,我可以使用正则表达式提取所需字符串并导入数据集:

gen targetfile= regexs(0) if(regexm(`datafiles', "[A-Z][A-Z][H][R][0-9][0-9][A-Z][A-Z]"))

然而,我也希望有一种不同的方法。

我发现这个问题非常令人费解,因为它是关于提取特定文件名的;但是如果你知道你想要的文件名,你可以直接键入它。如果观点不同,你可能需要修改你的问题

但是,让我们讨论一些技巧

将Stata变量名放入Stata变量(严格地说,是指数据集中的列)原则上是可能的,但这很少是最好的主意。您应该继续按照开始的方向进行,即定义并操作本地宏

在这种情况下,可以通过检查提取变量元素,但让我们展示如何删除一些常见元素:

. local names etbr41fl.dta ethr41fl.dta etir41fl.dta etkr41fl.dta etwi41fl.dta

. local names : subinstr local names ".dta" "", all

. local names : subinstr local names "et" "", all

. di "`names'"
br41fl hr41fl ir41fl kr41fl wi41fl
这就足够展示更多的技巧了,也就是你可以循环这些名称。事实上,通过您所演示的构造,您可以以任何方式实现这一点,不需要正则表达式或其他任何东西:

. local datafiles : dir . files  "*.dta"

. foreach f of local datafiles { 
      ... using "`f'" 
} 

 . foreach n of local names { 
      ... using "et`n'.dta" 
 }
这里的示例显示了在给定文本字符串时的一个细节,即通常需要使用
作为分隔符(并且很少有害)

注意。文件名中的大写和小写可能与此无关。斯塔塔会翻译

注意。你这么说

. gen datafiles = "`datafiles'"

给出空值。这可能是因为您在本地宏不可见的区域设置中执行了该语句。常见的例子有:从do文件编辑器窗口执行一个命令,从主命令窗口执行另一个命令;从do文件编辑器窗口逐个执行命令。这就是为什么本地宏如此命名;它们仅在同一代码块中可见

按照Nick的建议,继续使用本地宏,而不是将文件名放入Stata变量,下面是一些实现您所述目标的技巧。我同意Nick忽略Windows提供的文件名的大小写,这是一个不区分大小写的文件系统。我的示例将使用区分大小写的文件系统,但将匹配任何大小写或混合大小写的文件名

. dir *.dta

-rw-r--r--  1 lisowskiw  staff  1199 Jan 18 10:04 a space.dta
-rw-r--r--  1 lisowskiw  staff  1199 Jan 18 10:04 etbr41fl.dta
-rw-r--r--  1 lisowskiw  staff  1199 Jan 18 10:04 ethr41fl.dta
-rw-r--r--  1 lisowskiw  staff  1199 Jan 18 10:04 etir41fl.dta
-rw-r--r--  1 lisowskiw  staff  1199 Jan 18 10:04 etkr41fl.dta
-rw-r--r--  1 lisowskiw  staff  1199 Jan 18 10:04 etwi41fl.dta

. local datafiles : dir . files  "*.dta" 

. di `"`datafiles'"'
"a space.dta" "etbr41fl.dta" "ethr41fl.dta" "etir41fl.dta" "etkr41fl.dta" "etwi41fl.dta"

. foreach file of local datafiles {
  2.     display "`file' testing"
  3.         if regexm(upper("`file'"),"[A-Z][A-Z][H][R][0-9][0-9][A-Z][A-Z]") {
  4.             display "`file' matched!"
  5.             // process file here
.                 }
  6.         }
a space.dta testing
etbr41fl.dta testing
ethr41fl.dta testing
ethr41fl.dta matched!
etir41fl.dta testing
etkr41fl.dta testing
etwi41fl.dta testing

您可以使用
filelist
(来自SSC)创建文件名数据集。然后,您可以利用全套Stata数据管理工具来识别要定位的文件。要安装
文件列表
,请在Stata的命令窗口中键入:

ssc install filelist
下面是一个数据集的快速示例,它遵循提供的示例:

. filelist, norecur
Number of files found = 6

. list if strpos(upper(filename),".DTA")

     +---------------------------------+
     | dirname   filename        fsize |
     |---------------------------------|
  1. | .         ETBR41FL.dta   12,207 |
  2. | .         ETHR41FL.DTA   12,207 |
  3. | .         ETIR41FL.DTA   12,207 |
  4. | .         ETKR41FL.DTA   12,207 |
  5. | .         ETWI41FL.DTA   12,207 |
     +---------------------------------+

. keep if regexm(upper(filename), "[A-Z][A-Z][H][R][0-9][0-9][A-Z][A-Z]")
(5 observations deleted)

. list

     +---------------------------------+
     | dirname   filename        fsize |
     |---------------------------------|
  1. | .         ETHR41FL.DTA   12,207 |
     +---------------------------------+

. 
. * with only one observation in memory, use immediate macro expansion
. * to form the file name to read in memory
. use "`=filename'", clear
(1978 Automobile Data)

. describe, short

Contains data from ETHR41FL.DTA
  obs:            74                          1978 Automobile Data
 vars:            12                          18 Jan 2016 11:58
 size:         3,182                          
Sorted by: foreign

在这种特殊情况下,您实际上不需要使用正则表达式

strmatch()
函数将同样出色地完成这项工作:

local datafiles etbr41fl.dta ethr41fl.dta etir41fl.dta etkr41fl.dta etwi41fl.dta

foreach x of local datafiles {
    if strmatch(upper("`x'"), "*HR*") display "`x'"
}
ethr41fl.dta

upper()
功能的使用是可选的。

+1。这可能是OP的目标,但如果名称的精确匹配是目标,那么测试是否相等就足够了!正则表达式表明,目标实际上可能是找到一个包含HR的文件名,后跟一个嵌入在两对字母之间的2位数字;如果是这样的话,开头的那句话是对真正问题的一次拙劣的尝试。我同意。有时候,解决问题最难的部分是弄清楚问题到底是什么。10年的学术型计算支持让我学会了永远不要从表面上接受问题和断言。:-)@william是的,目标是查找包含HR的文件名。为了清晰起见,我编辑了开头的句子。我在一个块中运行了命令:
localdatafiles:dir。文件“*.dta”
gen datafiles=
“`datafiles'”
但给出了空的新变量。但是向数据文件部分添加额外的记号(`…`)的工作方式与上面的@william相同。我编辑了我的问题,并补充说我有几个文件和文件夹要处理,所以我需要自动化数据导入。从宏到变量的切换是因为
strupper
似乎不适用于宏。但我现在意识到,windows不存在小写字母的问题。谢谢你回来,但这里的细节还不清楚。你引用的声明应该有效
strupper()
和宏对于您这样的示例是兼容的。问题的编辑给出了一个更简单的答案:通配符
*hr*.dta
将捕获名称中包含
hr
的所有
.dta
文件。答案范围更广:无论哪种方式,都不清楚为什么你似乎认为这个问题仍然悬而未决,因为你还没有接受任何答案。你也没有解释为什么答案不是你想要的。答案解决了我的问题,我只是在分析中试着找出最合适的答案。好吧,但是使用正确的通配符有什么不对或不充分的地方吗?@nick Am n