Как составить новую строковую переменную используя bysort - PullRequest
0 голосов
/ 15 декабря 2018

Я хочу подготовить код Stata для генерации новой строковой переменной как suspect из идентифицированного urid на основе соответствующей оценки, меньшей или равной 60, и отсутствующей оценки в каждом said.

Вход:

primkey  ssuid  sup  urid  score
10312551  1255  601  122   60
10312552  1255  601  122   80
10312553  1255  601  123   90
10312554  1255  601  124   66
10312561  1256  601  122   40
10312562  1256  601  123   30
10312563  1256  601  124   .
10312564  1256  601  125   66
10312581  1258  602  126   80
10312582  1258  602  127   95
10312583  1258  602  127   100
10312584  1258  602  128   .

Выход:

ssuid  sup  suspect
1255   601  122
1256   601  122,123,124
1258   602  128

Поля переменных primkey и score не требуются при выводе.

Ниже приведен код, который я уже пробовал:

sort state ssuid urid sup
gen x=_n
gen suspect=.
replace suspect=urid if (score <=60 | score==.) & urid=urid[x-1]
drop x
sort state ssuid suspect
gen x=_n
tostring suspect, replace
replace suspect=suspect[x-1]+","+suspect if suspect!="." & ssuid==ssuid[x-1]
drop x
gen x=strlen(ssususpect_sup)
gsort state ssuid -x
drop x
gen x=_n
replace suspect=suspect_sup[x-1] if ssuid==ssuid[x-1]
drop x

bys ssuid:gen x=_n 
keep if x==1
drop x

Однако это не дает желаемого результата.

1 Ответ

0 голосов
/ 15 декабря 2018

Ваш пример не имеет полного смысла.

Для ssuid 1255 наименьший балл равен 60. Таким образом, ни один балл не ниже 60.

Для ssuid 1258 наименьший балл составляет 80.

Stata'sПравило состоит в том, что пропущенное число является произвольно большим положительным, поэтому никогда не должно быть меньше 60.

Кажется, что ваше правило меньше или равно 60 или отсутствует.

С этими исправлениями это работает для меня:

clear 
input primkey  ssuid  sup  urid  score
10312551  1255  601  122   60
10312552  1255  601  122   80
10312553  1255  601  123   90
10312554  1255  601  124   66
10312561  1256  601  122   40
10312562  1256  601  123   30
10312563  1256  601  124   .
10312564  1256  601  125   66
10312581  1258  602  126   80
10312582  1258  602  127   95
10312583  1258  602  127   100
10312584  1258  602  128   .
end 

egen tokeep = max(score <= 60 | missing(score)), by(ssuid) 
keep if tokeep 
drop tokeep 
drop if inrange(score, 61, .) 

bysort ssuid (primkey) : gen suspect = string(urid) if _n == 1 
by ssuid: replace suspect = suspect[_n-1] + ///
"," + string(urid) if _n > 1 & urid != urid[_n-1] 
by ssuid: keep if _n == _N 

keep ssuid sup suspect 
list 

     +---------------------------+
     | ssuid   sup       suspect |
     |---------------------------|
  1. |  1255   601           122 |
  2. |  1256   601   122,123,124 |
  3. |  1258   602           128 |
     +---------------------------+

РЕДАКТИРОВАТЬ Давайте посмотрим на оригинальный код.Я сделал несколько комментариев и нашел некоторый код, который можно уменьшить, и одну явную ошибку, но я выручил после этого.Проблемы должны быть воспроизводимыми!

sort state ssuid urid sup
gen x=_n
gen suspect=.
replace suspect=urid if (score <=60 | score==.) & urid=urid[x-1]
drop x
sort state ssuid suspect
gen x=_n
tostring suspect, replace
replace suspect=suspect[x-1]+","+suspect if suspect!="." & ssuid==ssuid[x-1]
drop x
gen x=strlen(ssususpect_sup)
gsort state ssuid -x
drop x
gen x=_n
replace suspect=suspect_sup[x-1] if ssuid==ssuid[x-1]
drop x
bys ssuid:gen x=_n 
keep if x==1
drop x

*1 There is nothing in the data example about a variable -state-. 
* What do you don't show, we need not try to replicate 

*2 Your use of x for _n isn't needed. You can use _n directly. 
* That saves 8 lines 

sort ssuid urid sup
gen suspect=.
replace suspect=urid if (score <=60 | score==.) & urid=urid[_n-1]
sort ssuid suspect
tostring suspect, replace
replace suspect=suspect[_n-1]+","+suspect if suspect!="." & ssuid==ssuid[_n-1]
gen x=strlen(ssususpect_sup)
gsort ssuid -x
drop x
replace suspect=suspect_sup[_n-1] if ssuid==ssuid[_n-1]
bys ssuid: keep if _n == 1 

*3 Your first three lines can be slimmed to one 

by sort ssuid urid (sup) : gen suspect = urid if (score <=60 | score==.) & urid=urid[_n-1]
sort ssuid suspect
tostring suspect, replace
replace suspect=suspect[_n-1]+","+suspect if suspect!="." & ssuid==ssuid[_n-1]
gen x=strlen(ssususpect_sup)
gsort ssuid -x
drop x
replace suspect=suspect_sup[_n-1] if ssuid==ssuid[_n-1]
bys ssuid: keep if _n == 1 

*4 It's simpler to create -suspect- as string in the first place
* so cut the -tostring- line  

bysort ssuid urid (sup) : gen suspect = string(urid) if (score <=60 | score==.) & urid=urid[_n-1]
sort ssuid suspect
replace suspect=suspect[_n-1]+","+suspect if suspect!="." & ssuid==ssuid[_n-1]
gen x=strlen(ssususpect_sup)
gsort ssuid -x
drop x
replace suspect=suspect_sup[_n-1] if ssuid==ssuid[_n-1]
bys ssuid: keep if _n == 1 

*5 bug: testing for equality needs == not = 

bysort ssuid urid (sup) : gen suspect = string(urid) if (score <=60 | score==.) & urid==urid[_n-1]
sort ssuid suspect
replace suspect=suspect[_n-1]+","+suspect if suspect!="." & ssuid==ssuid[_n-1]
gen x=strlen(ssususpect_sup)
gsort ssuid -x
drop x
replace suspect=suspect_sup[_n-1] if ssuid==ssuid[_n-1]
bys ssuid: keep if _n == 1 

*6 you refer to a variable -ssussusspect_sup- which you haven't supplied as 
* data, or created in your code. At this point I bail out. 
...