如何使用字符串后缀重命名许多变量

时间:2012-12-03 02:03:34

标签: foreach stata stata-macros

在Stata中,我有一组以pkg开头的变量。在其当前状态下,其结尾为数字:pkg1pkg2pkg3pkg4等等。

我需要将所有这些变量的结尾更改为字符串:pkgmzpkggmzpkgsppkgsptc等。

我有一列这些字符串结尾,我可以将其指定为本地列表。

例如:

local croplist mz gmz sp sptc mil cof suk tea ric

如何将数字结尾更改为字符串结尾?

我对代码的猜测可以在下面找到,???表示我在哪里难倒:

local croplist crops mz gmz sp sptc mil cof suk tea ric

foreach x of varlist pkg* {
    local new1 = substr(`x', 1, 3)
    local new2 = ???
    rename `x' ``new1'`new2''
    label var ``new1'`new2'' "Avg district level `new2' price"
}

我想知道使用regexr()命令是否更好,但想不出包含它的方法。

感谢任何帮助。

5 个答案:

答案 0 :(得分:10)

此处无需调用正则表达式。你有新的后缀;前缀pkg始终相同,因此不必重复提取它。问题的核心是同时在两个列表上循环。这是修复代码的一种方法。


local croplist mz gmz sp sptc mil cof suk tea ric
local j = 1 
foreach x of varlist pkg* {
    local sffx : word `j' of `croplist' 
    rename `x' pkg`sffx'
    label var pkg`sffx' "Avg district level `sffx' price"
    local ++j 
}

注意,Stata 12+中的rename可以处理此问题; regexr()是一个函数,而不是一个命令; http://www.stata-journal.com/sjpdf.html?articlenum=pr0009中的一般性讨论(有点过时,但与主要问题相关);你的rename命令上有太多的引号,所以它不起作用。

2018年7月30日编辑

我现在更倾向于使用gettoken

local croplist mz gmz sp sptc mil cof suk tea ric
foreach x of varlist pkg* {
    gettoken sffx croplist: croplist
    rename `x' pkg`sffx'
    label var pkg`sffx' "Avg district level `sffx' price"
}

本地宏croplist是一个堆栈。每次循环时,我们从堆栈中取出顶部项目,然后将其余部分留下。 每次循环

答案 1 :(得分:9)

这是另一种方法。 tokenize在编号为1的宏中放置单独的单词。嵌套引用``j''仅在初等代数中处理:首先计算内部宏引用。

 
tokenize "mz gmz sp sptc mil cof suk tea ric" 
forval j = 1/9 {
    rename pkg`j' pkg``j''
    label var pkg``j'' "Avg district level ``j'' price"
}

答案 2 :(得分:7)

Ben在评论中提到了增加本地宏中保存的计数器的问题。

Stata的本地宏通常用于保持字符串;串 字符可以是数字,因此保持数字是一种特殊情况,但是 自然是一个非常有用的。仅此线程已经显示了几个 例子。它有助于牢记这一历史。长期的语法 基于表格

local macname <contents> 

local macname = <expression> 

第一个表单复制到macname而第二个表单 在将结果分配给macname之前进行评估。该 增加计数器的主要方法是多个版本

local j = `j' + 1 

但语法

local ++j 
现在允许

。但是,虽然允许

local j++ 

不会像你期望的那样工作,尽管会发生什么是符合的 宏的第一个语法。

所以,如果你的背景看起来有点奇怪,那就是 可以理解,但本地宏用于字符串处理, 不算算。在这方面,马塔更像是主流。

我在

中写了关于循环和宏的教程

Cox,N.J。2002.如何面对坚韧的名单。 Stata Journal 2(2): 202-222

,所有人都可以访问

http://www.stata-journal.com/sjpdf.html?articlenum=pr0005

答案 3 :(得分:2)

从Stata 12+开始,rename可以通过多种方式处理此案例。

此方法创建一个包含变量名new_croplist的新宏pkgmz pkggmz pkgsp pkgsptc pkgmil pkgcof pkgsuk pkgtea pkgric,然后使用rename将模式pkg<digits>之后的变量重命名为new_croplist中指定的名称}。 pkg后面的数字不需要是连续的。

local croplist mz gmz sp sptc mil cof suk tea ric
local new_croplist
foreach name of local croplist {
    local new_croplist `new_croplist' pkg`name'
}
rename pkg# (`new_croplist')

第二种方法使用新的rename函数两次;和以前一样,这不需要原始名称中的连续数字。第一个命令将模式pkg<digits>的变量重命名为croplist中指定的名称。第二个命令将前缀pkg添加到新变量名称。

rename pkg# (`croplist')
rename (`croplist') pkg=

在这两种情况下,通常在使用rename命令(在Stata的文档中称为rename group)时,旧变量名的数量必须与新变量名的数量相匹配,因此make确保pkg#匹配的变量数与`croplist'中指定的新名称数相匹配。

答案 4 :(得分:1)

在@ Nick的优秀例子中使用计数器的另一种方法是使用 macro shift

clear

forvalues i = 1 / 9 {
    generate pkg`i' = runiform()
}

local croplist mz gmz sp sptc mil cof suk tea ric
tokenize "`croplist'"

foreach var of varlist pkg* {
    rename `var' pkg`1'
    label var pkg`1' "Avg district level `1' price"
    macro shift
}

您还可以使用ds命令获取以pkg开头的变量名称列表:

local croplist mz gmz sp sptc mil cof suk tea ric
tokenize "`croplist'"

ds pkg*

foreach var of varlist `r(varlist)' {
    rename `var' pkg`1'
    label var pkg`1' "Avg district level `1' price"
    macro shift
}

在这两种情况下,你都会得到:

pkgmz           float   %9.0g                 Avg district level mz price
pkggmz          float   %9.0g                 Avg district level gmz price
pkgsp           float   %9.0g                 Avg district level sp price
pkgsptc         float   %9.0g                 Avg district level sptc price
pkgmil          float   %9.0g                 Avg district level mil price
pkgcof          float   %9.0g                 Avg district level cof price
pkgsuk          float   %9.0g                 Avg district level suk price
pkgtea          float   %9.0g                 Avg district level tea price
pkgric          float   %9.0g                 Avg district level ric price