Stata计数子串

时间:2014-12-07 15:23:32

标签: count substring stata

我的表格如下:

ID         AQ_ATC     amountATC
.       "A05"                 1
123     "A05AA02"          2525
234     "A05AA02"          2525
991     "A05AD39"           190
.       "C10"                 1
441     "C10AA11"          4330
229     "C10AA22"          3100
.       "C05AA"               1
441     "C05AA03"           130

完整的8个字符AQ_ATC代码的计数已经正确。 较短的代码在表中是唯一的,并且是完整的8字符代码的子字符串(它们代表前x个字符)。 我要找的是整个表中较短代码的出现次数。 例如,在这种情况下,结果表将是

ID         AQ_ATC     amountATC
.       "A05"              2715       <-- 2525 + 190
123     "A05AA02"          2525
234     "A05AA02"          2525
991     "A05AD39"           190
.       "C10"              7430       <-- 4330 + 3100
441     "C10AA11"          4330
229     "C10AA22"          3100
.       "C05AA"             130       <-- 130
441     "C05AA03"           130

部分代码不重叠,我的意思是,如果有"C05"则不会有另一部分代码"C05A1&#34;。

我使用

创建了amountATC列
bysort ATC: egen amountATC = total(AQ_ATC==AQ_ATC)

我试图回收昨天收到的代码,但未能这样做。 我的尝试看起来像这样:

levelsof AQ_ATC, local(ATCvals) 

quietly foreach y in AQ_ATC { 
local i = 0
quietly foreach x of local ATCvals { 
    if strpos(`y', `"`x'"') == 1{
    local i = `i'+1
    replace amountATC = `i'
    }
 }
}

我的想法是使用一个柜台&#34;我&#34;每当AQ_ATC以另一个AQ_ATC代码开头时,将其增加1。然后我写了#34;我&#34;进入amountATC并且在我遍历我的AQ_ATC的整个表之后,我将得到一个&#34; i&#34; - 值将等于子字符串的出现量。然后我重置&#34;我&#34;为0并继续下一个AQ_ATC。 至少这就是我打算如何工作,它最终做的是将所有amountATC - 值设置为1.

我还试图研究不同的egen函数,例如noccur和moss,但是当我尝试安装软件包时,我的连接会保持超时。

1 个答案:

答案 0 :(得分:4)

好像你来自另一种语言而且你坚持使用循环时并非严格必要。 Stata在没有显式循环的情况下做很多事情,正是因为命令已经适用于所有观察。

一种方法是:

clear
set more off

input ///
ID         str15 AQ_ATC      amountATC
.       "A05"                 1
123     "A05AA02"          2525
234     "A05AA02"          2525
991     "A05AD39"           190
.       "C10"                 1
441     "C10AA11"          4330
229     "C10AA22"          3100
.       "C05AA"               1
441     "C05AA03"           130
end

*----- what you want -----

sort AQ_ATC ID
gen grou = sum(missing(ID))

bysort grou AQ_ATC: gen tosum = amountATC if _n == 1 & !missing(ID)
by grou: egen s = total(tosum)

replace amountATC = s if missing(ID)

list, sepby(grou)

修改

通过编辑,适用相同的原则。下面的代码会根据您的更改进行调整并略微更改代码(少一行):

*----- what you want -----

sort AQ_ATC
gen grou = sum(missing(ID))

bysort grou: gen s = sum(amountATC) if AQ_ATC != AQ_ATC[_n+1] & !missing(ID)
by grou: replace amountATC = s[_N] if missing(ID)

效率应该更高:

<snip>

bysort grou: gen s = sum(amountATC) if AQ_ATC != AQ_ATC[_n+1]
by grou: replace amountATC = s[_N] - 1 if missing(ID)

一些意见:

  1. sort是一个非常方便的命令。如果按AQ_ATC对数据进行排序,则它们的排列方式使得短(子)字符串放在相应的长字符串之前。

  2. by:前缀是基本的,非常有用,我注意到您可以在定义适当的组后使用它。我利用所有短(子)字符串都有missing(ID)的事实创建了这些组。

  3. 然后(由刚刚定义的组)您只想为每amountATC添加一个值(观察)。这就是条件if AQ_ATC != AQ_ATC[_n+1]的作用。

  4. 最后,replace返回原始变量。我通常会generate复制并使用它,因此我的原始变量不会受到影响。

  5. Nick Cox对by:前缀的优秀读物为Speaking Stata: How to move step by: step

    EDIT2

    另一种略有不同的方式:

    *----- what you want -----
    
    sort AQ_ATC
    gen grou = sum(missing(ID))
    
    egen t = tag(grou AQ_ATC)
    bysort grou: gen s = sum(amountATC * t)
    
    by grou: replace amountATC = s[_N] - 1 if missing(ID)