Merge 检查一个变量的每个值是否与另一个变量的任何值匹配

Merge 检查一个变量的每个值是否与另一个变量的任何值匹配,merge,stata,Merge,Stata,我想要类似于egen newvar=anymatch(oldvar1),values(oldvar2)的东西。这将创建一个指示符变量,显示oldvar2中的特定值是否包含在oldvar1中的任何位置。除了对anymatch的AIK之外,值只接受整数numlist 这将有很多用途,但这里是我的第一个示例:我有一个大型国家对数据集。我有一个Country1的子集,它有一个特定的属性。我想确定匹配子集中任何成员的Country2 让我们看看我是否可以制作一个玩具示例: +----------

我想要类似于
egen newvar=anymatch(oldvar1),values(oldvar2)
的东西。这将创建一个指示符变量,显示oldvar2中的特定值是否包含在oldvar1中的任何位置。除了对
anymatch
的AIK之外,
只接受
整数numlist

这将有很多用途,但这里是我的第一个示例:我有一个大型国家对数据集。我有一个Country1的子集,它有一个特定的属性。我想确定匹配子集中任何成员的Country2

让我们看看我是否可以制作一个玩具示例:

     +--------------------------------------------------+
     | pair   Country1   value_C1   Country2   valC1_g2 |
     |--------------------------------------------------|
  1. |   AB          A          1          B          0 |
  2. |   AC          A          2          C          0 |
  3. |   BA          B          3          A          1 |
  4. |   BC          B          4          C          1 |
  5. |   CA          C          5          A          1 |
     |--------------------------------------------------|
  6. |   CB          C          6          B          1 |
     +--------------------------------------------------+
_C1变量的值与Country1的属性相关。变量valC1_g2表示值_C1大于2。我想要一个变量,该变量指示Country2中的每个特定变量是否在
Country1的列表中的某个位置有匹配项(如果valC1\u g2

这似乎不是一个罕见的问题,但除了这个话题,我找不到任何直接解决这个问题的方法

这可以通过合并完成:

preserve // saves current data
tempfile localdata // initialize a temporary new dataset
  keep Country1 valC1_g2 // subsetting allows re-ordering of just these variables
  rename (Country1 valC1_g2) (Country2 valC2_g2) // renaming to match the target
  sort Country2 // this just facilitates the 1:1 merge
  save `localdata'
restore // bring back original data

sort Country2 
merge  Country2 using `localdata' // this re-orders the subset to align with Country2 
  sort Country1 pair  // this resets the dataset to the original order

list, abbreviate(10) separator(0)

     +-------------------------------------------------------------+
     | pair   value_C1   Country1   Country2   valC1_g2   valC2_g2 |
     |-------------------------------------------------------------|
  1. |   AB          1          A          B          0          1 |
  2. |   AC          2          A          C          0          1 |
  3. |   BA          3          B          A          1          0 |
  4. |   BC          4          B          C          1          1 |
  5. |   CA          5          C          A          1          0 |
  6. |   CB          6          C          B          1          1 |
     +-------------------------------------------------------------+

我发现这种方法有几个问题

首先,您将看到我的
merge
语法使用旧语法,因为Country2没有唯一标识我的数据。(我猜这意味着我在用新语法做m:m?merge的文档中说这是不可能的。)pair变量扮演着这个角色,但我不能按pair合并,否则我将无法获得所需的重新排序。也许我担心的太多了

第二,我如何检查它是否有效?之后,我想比较Country1和Country2中的国家ID,看看它们是否具有相同的值集<代码>比较不起作用,因为值没有按行排列。我唯一能想到做的就是再次使用merge重新排序后进行比较,但这实际上只是撤销了我刚才所做的

如果能提出更好的方法,我将不胜感激

一个变量,用于指示如果valC1_g2,Country2是否在Country1列表中

您的描述并不十分清楚,可能会导致不同的理解:

  • 有些人可能会将其解释为相应观察(配对)中的Country1具有valC1_g2=1(如Pearly Spencer的代码中所示,如果您可能熟悉mata,这是优雅且“令人愉快的”)

  • 同时,其他人可能认为相关观察(配对)中的Country2与某处的Country1相同,并且Country1的(最大)valC1_g2=1。请注意,这里提到了(max),因为对于您的小样本,假设任何国家1在任何观察中都应该有相同的valC1_g2,则无法确定

对我来说,你的代码意味着第二种理解。如果是这样的话,在代码中多添加一行代码可以帮助您解决问题。事实上,还有其他一些方法(可能更优雅),但这一种可能会节省您跟进的时间

preserve
tempfile localdata
keep Country1 valC1_g2

*(Addedline)
collapse (max) valC1_g2 if valC1_g2, by(Country1)

rename (Country1 valC1_g2) (Country2 valC2_g2)
save `localdata'
restore
sort Country2

* (It is better to use the new merge syntax, despite your old one might work)
merge m:1 Country2 using `localdata', keep(master match) nogen
编辑。你编辑的版本,确认了第二种理解,使它更清晰了一点。提高透明度的另一个建议是,“后续部分”(比较两个国家ID)不应与“第二部分”(检查第一部分代码的逻辑)放在同一行。这是两个不同的问题

下面的代码仍然使用-merge-作为主要工具,预计将通过以下方式为您的问题提供服务:

  • 创建变量(C2inListC1)以检查Country2是否在 国家名单1

  • 如果Country2在Country1的列表中,则其valC2_g2将具有对应Country1的valC1_g2的(最大)值。提到(max)是因为,如上所述,到目前为止,还不能确定每个国家1应该有相同的valC1_g2

  • 创建变量(C1inListC2)以检查Country1是否在Country2列表中。然后,您可以使用C2inListC1和C1inListC2的信息来检查Country1和Country2是否具有相同的值集。只有当“所有国家2都在国家1的列表中”和“所有国家1都在国家2的列表中”时,两者才是相同的

  • 请注意,尽管还有其他一些方法(编码可能更简洁或更优雅,特别是对于创建C2inListC1),-merge提供了非常清晰明了的逻辑,似乎是收集valC1_g2信息的最佳工具。它应该只在正确的逻辑上起作用。编码只是将逻辑本身翻译成编码语言

    tempfile ListC1 ListC2
    
    preserve
    collapse (max) valC1_g2, by(Country1)
    rename (Country1 valC1_g2) (Country2 valC2_g2)
    save `ListC1', replace
    restore
    
    preserve
    contract Country2
    ren Country2 Country1
    save `ListC2', replace
    restore
    
    merge m:1 Country2 using `ListC1', keep(master match) gen(C2inListC1)
    merge m:1 Country1 using `ListC2', keep(master match) gen(C1inListC2) keepusing(Country1)
    
    recode C2inListC1 C1inListC2 (3=1) (else=0)
    label values C2inListC1 C1inListC2 none
    
    count if C2inListC1==0 | C1inListC2==0
    if r(N) == 0{
    di "Country1 and Country2 have the same values set"
    }
    else {
    di in red "Country1 and Country2 do NOT have the same values set"
    }
    

    编辑问题以澄清。谢谢您,@Romalpa Akzo!我可以问2个跟进Qs以确保我理解吗?首先,如果每个Country1只有一个valC1_g2值(因为它们派生自Country1的属性),代码将如何更改?我想你可以
    折叠(第一)
    而不是
    (最大)
    。就这些吗?第二,什么是“
    keepusing(Country1)
    ”?它在Country1上合并,并保留(主匹配),因此最后一位似乎不必要。我错过什么了吗?再次感谢!(1) 是的。在这种情况下,塌陷(first)或(firstnm)甚至(mean)将起作用。无论如何,(max)在这个问题上似乎“更安全”。(2) keepusing(Country1)只是用于忽略由-contract-command创建的_freq变量。你可以省略keepusing(Country1)来了解区别。