6

在 Stata 中,我有一组变量都以pkg. 在当前状态下,它们的结尾是数字:pkg1pkg2pkg3pkg4

我需要将所有这些变量的结尾更改为字符串:pkgmz、、、pkggmzpkgsppkgsptc

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

例如:

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(),但想不出包含它的方法。

任何帮助表示赞赏。

4

5 回答 5

10

这是另一种方法。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"
}
于 2012-12-03T08:01:59.123 回答
9

这里不需要调用正则表达式。你有新的后缀;前缀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 
}

另请注意rename,在 Stata 12+ 中可以处理此问题;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是一个堆栈。每次循环时,我们都会从堆栈中取出顶部的项目,并将其余部分留给下一次。每次循环

于 2012-12-03T07:21:32.973 回答
7

Ben 在评论中询问了有关在本地宏中增加计数器的问题。

Stata 的本地宏通常用于保存字符串;字符串字符可以是数字,所以持有数字是一种特殊情况,但自然是一种非常有用的情况。仅此线程就显示了几个示例。这有助于牢记这段历史。长期存在的语法基于形式

local macname <contents> 

local macname = <expression> 

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

local j = `j' + 1 

但语法

local ++j 

现在是允许的。然而,虽然允许

local j++ 

不会像您预期的那样工作,尽管发生的情况与宏的第一个语法一致。

因此,如果考虑到您的背景,这看起来有点奇怪,那是可以理解的,但是本地宏是用于字符串处理的,而不是算术的。Mata 在这方面更像主流。

我写了一个关于循环和宏的教程

Cox, NJ 2002。如何以坚韧的态度面对名单。统计杂志2(2): 202-222

所有人都可以访问

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

于 2012-12-10T10:16:49.947 回答
1

从 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命令时(rename group在 Stata 的文档中引用),旧变量名的数量必须与新变量名的数量匹配,因此请确保匹配的变量数量与新变量名pkg#匹配在“croplist”中指定的名称。

于 2015-06-18T22:20:27.590 回答
0

在@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
于 2018-05-26T20:20:48.103 回答