【问题标题】:Stata: replace, if, forvaluesStata:替换,如果,forvalues
【发布时间】:2013-10-31 21:01:37
【问题描述】:
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 及以后。

【问题讨论】:

  • “不起作用”是什么意思?你能说得更具体点吗?
  • 我将结果添加到原始问题中。谢谢。

标签: loops if-statement stata


【解决方案1】:

双重不等式,例如

(`min' <= distance_km < 1)

根据数学惯例,这在 Stata 中显然是合法的。否则,您的代码将触发语法错误。但是,Stata 在整个表达式被计算之前不会进行计算。这里的括号无关紧要,因为关键是如何评估它们的内容。事实证明,结果不太可能是你想要的。

更详细地说:Stata 从左到右解释这个表达式如下。第一个等式

`min' <= distance_km

是真还是假,因此被评估为 0 或 1。显然您想要选择这样的值

distance_km >= `min' 

对于这样的值,上面的不等式为真并返回 1。Stata 然后将 1 的结果向前并转向第二个不等式,评估

1 < 1 

(即第一个不等式的结果&lt; 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()

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

  1. 您可以同时destring 多个变量。

  2. generate 将常量放入变量中是低效的。为此目的使用scalars。 (但是,如果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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-11
    • 1970-01-01
    相关资源
    最近更新 更多