2014-11-06 198 views
2

我试图在Stata中编写一个foreach循环,它会自动替换我的数据库中缺失值(".a")的所有"n.a."值。我有以下代码:foreach所有缺失值

foreach var of varlist `allvar' { 
    replace `var' = ".a" if `var' == "n.a." 
} 

我定义我的varlist中,在我的数据集中的所有变量,但我得到一个"type mismatch"错误。我只用一个变量尝试了replace命令,我注意到这个错误与数字变量有关。任何想法如何使这个工作与foreach所有变量?或者我需要选择只是字符串变量?

+0

请注意,Stata不会为字符串'“.a”附加任何特殊含义'它会为数字值'.a'附加特殊含义。尽管线程是关于如何去做的,但用需要解释的另一个字符串替换字符串值并不是一个明显有用的步骤。 – 2017-11-22 10:37:03

回答

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." 
} 

这个有用的警告来自尼克考克斯: “另外,注意在使用等号分配一个字符串转换为当地的宏在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 
+0

从@Nick代码的最终简化工作顺利。我也尝试了其他代码,对我来说,对于我的具体情况来说,这些代码对我来说是非常有用的,并且可以理解它。非常有帮助,谢谢大家。 – Emanuel 2014-11-07 15:31:39

+1

请注意,'foreach var varlist'不是我所建议的。来自'ds'的输出已经(a)已知是一个varlist(b)保证被解析成不同的变量名。因此'foreach var in'会正常工作,并说明否则会迫使Stata做少量不必要的工作。 – 2014-11-07 16:34:29

+0

对不起。这是我没有从行中删除'varlist'的疏忽。 – 2014-11-07 19:59:08

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”并不是真正的错误。这只是文字,没有特别的意义。

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对应值标签的数值等于“NA”的东西,如:

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 missinghttps://stackoverflow.com/a/25942520/2077064,它更详细地解释了replace中的条件如何工作。

如果您需要选择一种特定类型的变量,Aspen Chen已经提到了ds。其他选项可以在

中发现的塔塔杂志(2010年) 10,第2号,第281-296, 谈到塔塔:寻找变量, 由尼克·考克斯。 (可在网上免费下载)

+0

这是很棒的附加信息。将扩展宏功能应用于命令会更有效率。 – 2014-11-07 05:28:28

+0

真的很有帮助@罗伯托进入foreach,并理解它,为我的具体情况。 – Emanuel 2014-11-07 15:35:14

+0

不客气。我仍然认为你的问题不是在'foreach'循环中,而是在Stata中的标签,缺失和变量类型的概念。如果您有指定“.a”来表示错误的字符串变量,那么这是您的选择,并且可以最终处理。但我只想强调,Stata不承认这是失踪的,因此,它似乎不是自然的走向。说实话,我仍然不确定你的问题是什么,我的答案是基于猜测。但是,我不知道这个猜测是否正确。这对未来的读者来说很有帮助。 – 2014-11-07 15:50:18