use "locationdata.dta", clear
gen ring=.
* Philly City Hall
gen lat_center = 39.9525468
gen lon_center = -75.1638855
destring(INTPTLAT10), replace
destring(INTPTLON10), replace
vincenty INTPTLAT10 INTPTLON10 lat_center lon_center , hav(distance_km) inkm
quietly su distance_km
local min = r(min)
replace ring=0 if (`min' <= distance_km < 1)
local max = ceil(r(max))
* forval loop does not work
forval i=1/`max'{
local j = `i'+1
replace ring=`i' if (`i' <= distance_km < `j')
}
我正在从一个点开始画1公里的戒指。代码的最后一部分(forval
)不起作用。这里有什么问题?
修改
forval
部分的结果如下:
. forval i=1/`max'{
2. local j = `i'+1
3. replace ring=`i' if `i' <= distance_km < `j'
4. }
(1746 real changes made)
(0 real changes made)
(0 real changes made)
(0 real changes made)
....
因此,替换不适用于i = 2
及更高版本。
答案 0 :(得分:2)
双重不等式,例如
(`min' <= distance_km < 1)
根据数学惯例有意义的在Stata中显然是合法的。否则,您的代码将触发语法错误。但是,在评估整个表达式之前,Stata不会进行评估。这里的括号并不重要,因为关键是如何评估它们的内容。事实证明,结果不太可能是你想要的。
更详细:Stata从左到右解释此表达式,如下所示。第一个平等
`min' <= distance_km
为真或假,因此评估为0或1.显然,您想要选择
这样的值distance_km >= `min'
并且对于这样的值,上面的不等式为真,并返回1.Stata然后将1的结果转向第二个不等式,评估
1 < 1
(即第一个不等式< 1
的结果),但这对于这些值是错误的。相反,
(`min' <= distance_km < 1)
将被评估为
0 < 1
- 这是真的(返回1) - 当且仅当
`min' > distance_km
简而言之,您打算采用不同的方式表达,即
(`min' <= distance_km) & (distance_km < 1)
我猜想这是你问题的根源。
请注意,Stata具有inrange()
功能,但这并不是您想要的。
但是,所有这一切,从查看你的代码,不等式和你的循环似乎都是非常不必要的。你希望你的戒指间隔为1公里,所以
gen ring = floor(distance_km)
在调用vincenty
后,可以替换整个代码块,因为floor()
向下舍入整数结果。你似乎知道它的双胞胎ceil()
。
其他一些小点,偶然但值得注意:
您可以一次destring
多个变量。
将常量放在generate
的变量中是效率低下的。为此目的使用scalar
。 (但是,如果vincenty
需要变量作为输入,则会覆盖此点,但会指出vincenty
过于严格。)
summarize, meanonly
更适合计算最小值和最大值。选项名称在这里具有误导性。有关讨论,请参阅http://www.stata-journal.com/sjpdf.html?articlenum=st0135。
作为一般Stata实践的问题,您的帖子应该解释用户编写的vincenty
来自何处,尽管在这种情况下似乎与此无关。
为了完整性,这里是重写,但您需要根据数据进行测试。
use "locationdata.dta", clear * Philly City Hall scalar lat_center = 39.9525468 scalar lon_center = -75.1638855 destring INTPTLAT10 INTPTLON10, replace vincenty INTPTLAT10 INTPTLON10 lat_center lon_center , hav(distance_km) inkm gen ring = floor(distance_km)