我正在尝试在Stata中编写一个foreach
循环,它会自动替换我的数据库中缺少值("n.a."
)的所有".a"
值。我有以下代码:
foreach var of varlist `allvar' {
replace `var' = ".a" if `var' == "n.a."
}
我使用我的数据集中的所有变量定义了我的varlist,但是我收到"type mismatch"
错误。我只用一个变量尝试replace
命令,我注意到错误与数字变量有关。任何想法如何使foreach
使用所有变量?或者我是否只需要选择字符串变量?
答案 0 :(得分:4)
考虑一些例子。
变量是数字但附加了标签。带有" n.a。"标签的观察结果被错过取代了。
clear
input ///
x
1
1
2
3
3
end
label define lblx 1 "a" 2 "b" 3 "n.a."
label values x lblx
list
list, nolabel
foreach var of varlist _all {
replace `var' = .a if `var' == 3
}
list, nolabel
count if missing(x)
变量是字符串类型。字符串被其他字符串替换;就Stata而言," .a" s并不是真正的错失。它只是文字而没有特殊含义。
clear
input ///
str5 x
a
a
b
n.a.
n.a.
end
list
foreach var of varlist _all {
replace `var' = ".a" if `var' == "n.a."
}
list
以下不起作用,也许是你的情况。你有一个数字变量(再次带有标签),你要求Stata检查字符串字符。因此,存在类型不匹配。
clear
input ///
x
1
1
2
3
3
end
label define lblx 1 "a" 2 "b" 3 "n.a."
label values x lblx
list
foreach var of varlist _all {
replace `var' = ".a" if `var' == "n.a."
}
实际上,您的代码正在将变量称为字符串类型(因为循环中使用了引号)。如果要使用扩展缺失值(.a
),则该变量必须为数字。系统缺失和延长缺失仅适用于它们。
字符串类型唯一缺失的是空白(""
)。
由于您报告的错误,您似乎有数字变量。如果您的变量都是字符串类型,那么您将不会遇到类型不匹配错误。不过,你提到
一些" n.a。" ,我认为是价值标签。值标签的基础是一些数值。您可以看到它们正在运行list, nolabel
。
如果是这种情况,您可以replace
对应于值标签的数字值等于" n.a。",类似于:
clear
*----- example data -----
input ///
x y
1 1
1 4
2 4
3 4
3 2
end
label define lblx 1 "a" 2 "b" 3 "n.a."
label values x lblx
label define lbly 1 "a" 2 "b" 4 "n.a."
label values y lbly
list
list, nolabel
*----- what you want -----
foreach var of varlist _all {
replace `var' = .a if `var' == "n.a.":`:value label `var''
}
// check
list, nolabel
count if missing(x)
count if missing(y)
请注意,对于变量x
,值标签n.a.
映射到值3,而对于变量y
,它映射到值4.因此,对于一个变量,想要替换3的值,而另一个值为4.代码将自动处理。此外,Stata现在将替换值识别为缺失值。
请参阅help labels
,help missing
和https://stackoverflow.com/a/25942520/2077064,其中详细介绍了replace
中的条件是如何运作的。
如果您需要选择一种特定类型的变量,Aspen Chen已经提到了ds
。其他选项可以在
The Stata Journal(2010) 10,第2期,第281-296页, Speaking Stata:查找变量, 作者:Nick Cox。 (可在网上免费获得。)
答案 1 :(得分:3)
代码确实只适用于字符串变量。考虑一下
行replace `var' = ".a" if `var' == "n.a."
在此行中的两个条件下返回type mismatch
错误:尝试将字符串".a"
(与缺失值.a
不同)分配给数字变量,并且试图检查数字变量是否等于字符串"n.a."
。
以下代码仅通过选择字符串变量来避免此问题(感谢Nick Cox提出的简化建议)。
ds,has (type string)
foreach var in `r(varlist)' {
replace `var' = ".a" if `var' == "n.a."
}
这个有用的警告来自Nick Cox: "另外,请注意何时使用等号将字符串分配给本地宏。在Stata的许多版本中,由于字符串表达式的长度限制,字符串将被截断。"
阅读Roberto的回答
后添加 罗伯托的例子非常有用。特别是,我还没有想到"n.a."
作为价值标签的问题。我扩展了其中一个示例,并使用缺少值"n.a."
替换标记为.a
的值的代码。
clear
input x y
3 2
1 3
2 3
3 3
1 1
end
label define lblx 1 "a" 2 "b" 3 "n.a."
label values x y lblx
list
foreach var of varlist _all {
loc na "" // reset local
loc vallab "" // reset local
loc vallab:value label `var'
qui levelsof `var',l(lvs)
foreach val of local lvs {
loc na: label `vallab' `val'
replace `var'=.a if "`na'"=="n.a." & `var'==`val'
}
}
list