1
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

4

1 回答 1

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) 

可以在调用 后替换整个代码块,vincentyfloor()整数结果向下取整。你似乎知道它的孪生兄弟ceil()

其他一些小点,偶然但值得注意:

  1. 您可以destring一次使用多个变量。

  2. 将常量放入变量中generate是低效的。scalar为此目的使用s。(但是,如果vincenty需要变量作为输入,那将覆盖这一点,但它指出这vincenty太严格了。)

  3. summarize, meanonly更适合仅计算最小值和最大值。不可否认,选项名称在这里具有误导性。请参阅http://www.stata-journal.com/sjpdf.html?articlenum=st0135进行讨论。

作为一般的 Stata 实践问题,您的帖子应该解释用户编写的vincenty来自哪里,尽管在这种情况下这似乎无关紧要。

为了完整起见,这里是一个重写,尽管您需要根据您的数据对其进行测试。

使用“locationdata.dta”,清除
 *费城市政厅
 标量 lat_center = 39.9525468
 标量 lon_center = -75.1638855
 destring INTPTLAT10 INTPTLON10,替换
 vincenty INTPTLAT10 INTPTLON10 lat_center lon_center , hav(distance_km) inkm
 gen ring = floor(distance_km)
于 2013-10-31T23:17:03.730 回答