基于正则表达式从文件夹导入文件
Import file from a folder based on a regular expression
我正在处理 DHS 数据,其中涉及位于不同文件夹中的具有一致命名的各种数据文件。每个文件夹都包含特定国家和调查年份的数据。
我想导入名称由组件 'HR' 组成的数据集,例如我有 ETHR41FL.DTA
。 'HR' 部分是一致的,但名称的其他部分因国家和调查年份而异。我需要一次处理一个数据集,然后转到下一个数据集,因此我相信自动搜索会有所帮助。
运行 下面的命令给出:
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
我认为下一步是将上面宏 datafiles
的值存储到一个变量中(因为 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'"
如何将 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"
}
此处的示例显示了给出文字字符串时的一个细节,即 " "
通常需要作为分隔符(而且很少有害)。
注意。文件名中的大写和小写在这里可能无关紧要。 Stata 会翻译。
注意。你说
. gen datafiles = "`datafiles'"
给出空值。这可能是因为您在本地宏不可见的语言环境中执行了该语句。常见的例子是:从 do-file 编辑器 window 执行一个命令,从主命令 window 执行另一个命令;从 do-file 编辑器 window 中一条一条地执行命令。这就是局部宏如此命名的原因;它们 仅 在同一代码块中可见。
按照 Nick 的建议继续使用本地宏而不是将文件名放入 Stata 变量,这里有一些技术可以实现您所说的 objective。我同意 Nick 忽略 Windows 提供的文件名的大写,这是一个 case-insensitive 文件系统。我的示例将使用 case-sensitive 文件系统,但将匹配任何大文件名或小文件名或 mixed-case 文件名。
. 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 数据管理工具来识别您想要定位的文件。要安装 filelist
,请输入 Stata 的命令 window:
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()
函数的使用是可选的。
我正在处理 DHS 数据,其中涉及位于不同文件夹中的具有一致命名的各种数据文件。每个文件夹都包含特定国家和调查年份的数据。
我想导入名称由组件 'HR' 组成的数据集,例如我有 ETHR41FL.DTA
。 'HR' 部分是一致的,但名称的其他部分因国家和调查年份而异。我需要一次处理一个数据集,然后转到下一个数据集,因此我相信自动搜索会有所帮助。
运行 下面的命令给出:
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
我认为下一步是将上面宏 datafiles
的值存储到一个变量中(因为 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'"
如何将 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"
}
此处的示例显示了给出文字字符串时的一个细节,即 " "
通常需要作为分隔符(而且很少有害)。
注意。文件名中的大写和小写在这里可能无关紧要。 Stata 会翻译。
注意。你说
. gen datafiles = "`datafiles'"
给出空值。这可能是因为您在本地宏不可见的语言环境中执行了该语句。常见的例子是:从 do-file 编辑器 window 执行一个命令,从主命令 window 执行另一个命令;从 do-file 编辑器 window 中一条一条地执行命令。这就是局部宏如此命名的原因;它们 仅 在同一代码块中可见。
按照 Nick 的建议继续使用本地宏而不是将文件名放入 Stata 变量,这里有一些技术可以实现您所说的 objective。我同意 Nick 忽略 Windows 提供的文件名的大写,这是一个 case-insensitive 文件系统。我的示例将使用 case-sensitive 文件系统,但将匹配任何大文件名或小文件名或 mixed-case 文件名。
. 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 数据管理工具来识别您想要定位的文件。要安装 filelist
,请输入 Stata 的命令 window:
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()
函数的使用是可选的。