use*_*050 0 foreach loops nested substring stata
我刚刚开始学习Stata,我很难过.我的问题是:我有两个不同的变量,ATC并且A,其中A可能是子串ATC.现在我想,以纪念所有的意见中,A是的一个子ATC带OK = 1.
我使用一个简单的嵌套循环尝试了这个:
foreach x in ATC {
foreach j in A {
replace OK = 1 if strpos(`x',`j')!=0
}
}
Run Code Online (Sandbox Code Playgroud)
但是,每当我运行此循环时,即使应该有足够的数据,也不会进行任何更改.我觉得我应该给出一个索引来指定哪个OK被更改(属于ATC/ x的那个),但我不知道如何做到这一点.这可能非常简单,但我已经挣扎了一段时间.
我应该澄清一下:我的A列表与主列表分开(只是附加到它),并且只包含我用来识别ATC我想要的s的唯一键.所以我有~120个A键和几百万个ATC键.我想要做的是迭代每个ATC单键的每个A键,并标记那些ATC具有A该限定条件的键.
这意味着我没有的(完整的元组ATC,A,OK),但不同的大小,而不是单独的列表.例如:我有
ATC OK A
ABCD 0 .
EFGH 0 .
... ... ...
. . AB
. . ET
Run Code Online (Sandbox Code Playgroud)
并希望结果"ABCD"已经OK被标记为1同时"EFGH"保持在0.
我们可以将您的问题分成两部分.你的标题意味着循环问题,但你的循环只相当于
replace OK = 1 if strpos(ATC, A)!=0
Run Code Online (Sandbox Code Playgroud)
因此循环的使用似乎无关紧要.这留下了子串比较.
让我们举个例子:
. set obs 3
obs was 0, now 3
. gen OK = 0
. gen A = cond(_n == 1, "42", "something else")
. gen ATC = "answer is 42"
. replace OK = 1 if strpos(ATC, A) != 0
(1 real change made)
. list
+------------------------------------+
| OK A ATC |
|------------------------------------|
1. | 1 42 answer is 42 |
2. | 0 something else answer is 42 |
3. | 0 something else answer is 42 |
+------------------------------------+
Run Code Online (Sandbox Code Playgroud)
它运作正常; 如果你认为你有不同的东西,你真的需要给出一个可重复的例子.
至于指定应该更改变量的位置:您的代码正是如此,正如上面的示例所示.
此更新使问题变得清晰.当您指定给出的语法时,Stata将仅查找匹配子字符串的相同观察.Stata中的变量是数据集中的字段.要循环一组值,这样的事情就足够了
gen byte OK = 0
levelsof A, local(Avals)
quietly foreach A of local Avals {
replace OK = 1 if strpos(ATC, `"`A'"') > 0
}
Run Code Online (Sandbox Code Playgroud)
笔记:
指定byte减少存储空间.
您可能需要if或in限制levelsof.
quietly删除有关已更改值的消息.调试时,通常最好省略.
> 0可以省略,strpos()因为在逻辑比较中自动将其视为真.见这个FAQ.