我在Stata中有一个包含50个变量的数据文件
j-r-hp j-p-hp j-m-hp p-c-hp p-r-hp p-p-hp p-m-hp ... etc,
我想在对之间执行加权kappa,因此第一个可能是
kap j-r-hp j-p-hp, wgt(w2)
,接下来就是
kap j-r-hp j-m-hp, wgt(w2)
我是Stata的新手。是否有一种直接使用循环的方法,如foreach
循环?
答案 0 :(得分:3)
您的变量名称在Stata中不是合法名称,因此我在下面的示例中将连字符更改为下划线。另外,我不知道执行加权kappa意味着什么,所以我的回答使用随机正常变量和corr[elate]
命令。您可以使用Stata留下的结果r()
(请参阅return list
)来收集单独分析的结果。
我们的想法是使用local
将变量收集到列表中,然后循环遍历该列表中的每个元素(但使用continue
跳过重复的对)。如果您有许多带有结构化名称的变量,则可以改为使用ds
,r(varlist)
留下r()
。请查看宏的帮助文件(help macro
和{ {1}}),尤其是用于解析'的宏扩展函数部分。希望这会有所帮助。
help extended_fcn
答案 1 :(得分:3)
您可以利用用户编写的命令tuples
(运行ssc install tuples
):
clear
set more off
*----- example data -----
set obs 100
local vars j_r_hp j_p_hp j_m_hp p_c_hp p_r_hp p_p_hp p_m_hp
foreach var of local vars {
gen `var' = abs(round(rnormal()*100))
}
*----- what you want -----
tuples `vars', min(2) max(2)
forvalues i = 1/`ntuples' {
display _newline(3) "variables `tuple`i''"
kappa `tuple`i''
}
如何将变量名称组合在一起以将它们输入tuples
取决于数据集。
答案 2 :(得分:2)
这是@Matthijs对有用答案的一种变体,但它确实不太适合评论。主要的额外曲折是
使用tokenize
来避免重复使用word
#of
。在tokenize
之后,参数的单独单词(这里是单独的变量名称)保存在宏1中。因此tokenize a b c
将a
置于本地宏1中,b
置于本地宏2中,c
置于局部宏3中。嵌套宏引用的处理方式与初等代数中的括号表达式完全相同;首先评估内部的内容。
直接关注对角线一侧的部分结果概念矩阵。小技巧是确保一个矩阵下标超过其他下标。
随机正常输入对kap
没有意义,但您将以任何方式使用自己的数据。
clear
set obs 100
local vars j_r_hp j_p_hp j_m_hp p_c_hp p_r_hp p_p_hp p_m_hp
foreach var of local vars {
gen `var' = rnormal()
}
tokenize `vars'
local p : word count `vars'
local pm1 = `p' - 1
forval i = 1/`pm1' {
local ip1 = `i' + 1
forval j = `ip1'/`p' {
di "``i'' and ``j''"
kap ``i'' ``j''
di
}
}
答案 3 :(得分:1)
我想我可以添加自己的答案,并强调一些事情。
首先要注意的是,对于新用户来说,最直接的"这样做的方法可能包括将所有变量硬编码到local
中以在循环中使用(如其他答案所示),或者使用通配符引用它们并为每个组写入多个循环。请参阅下面的示例,了解如何使用通配符:
clear *
sysuse auto
/* Rename variables to match your .dta file and identify groups */
rename (price mpg rep78) (j_r_hp j_p_hp j_m_hp)
rename (headroom trunk weight) (p_c_hp p_r_hp p_m_hp)
rename (length turn displacement foreign) (z_r_hp z_m_hp z_p_hp z_c_hp)
/* Loop over all variables beginning with j and ending hp */
foreach x of varlist j*hp {
foreach i of varlist j*hp {
if "`x'" != "`i'" & "`i'" >= "`x'"{ // This section ensures you get only
// unique pairs of x & i
kap `x' `i'
}
}
}
/* Loop over all variables beginning with p and ending hp */
foreach x of varlist p*hp {
* something involving x
}
* etc.
现在,根据您拥有的群组数量或您拥有的变量数量,这可能看起来并不简单。
这提出了我想提及的第二件事。在硬编码许多变量或许多重复命令变得麻烦的情况下,我倾向于支持程序化解决方案。这通常涉及预先编写更多代码,但在许多情况下往往至少是可以推广的,并且如果您有需要而无需全部编写,将允许您轻松评估数百个变量。
下面的代码使用describe
的返回结果,以及一些foreach
循环和一些扩展宏函数来对变量执行kappa
命令,而不必将它们存储在手动local
。
clear *
sysuse auto
rename (price mpg rep78) (j_r_hp j_p_hp j_m_hp)
rename (headroom trunk weight) (p_c_hp p_r_hp p_m_hp)
rename (length turn displacement foreign) (z_r_hp z_m_hp z_p_hp z_c_hp)
/*
use gear_ratio as an arbitrary weight, order it first to easily extract
from the local containing varlist
*/
order gear_ratio, first
qui describe, varlist
local Varlist `r(varlist)' // store varlist in a local macro
preserve // preserve data so canges can be reverted back
foreach x of local Varlist {
capture confirm numeric variable `x'
if _rc {
drop `x' // Keep only numeric variables to use in kappa
}
}
qui describe, varlist // replace the local macro varlist with now numeric only variables
local Varlist `r(varlist)'
local vars : list Varlist - weight // remove weight from analysis varlist
foreach x of local vars {
foreach i of local vars {
if "`x'" != "`i'" & "`i'" >= "`x'" {
gettoken leftx : x, parse("_")
gettoken lefti : i, parse("_")
if "`leftx'" == "`lefti'" {
kap `x' `i'
}
}
}
}
restore
对于新用户来说,这里当然会有一个学习曲线,但我发现使用宏,循环和返回的结果非常有效地增加了我的程序和文件的灵活性 - 我强烈建议任何人使用Stata至少可以研究这三个主题的基础知识。