Stata:计算预定义长度的连续出现的次数

编程入门 行业动态 更新时间:2024-10-24 17:29:59
本文介绍了Stata:计算预定义长度的连续出现的次数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我的数据集中的观察数据包含每个球员的移动历史。我想计算一下在游戏的上半场和下半场,连续几步棋的长度(2步、3步和3步以上)。序列不能重叠,即序列1111应视为长度为4的序列,而不是长度为2的2个序列。也就是说,对于这样的观察:

+-------+-------+-------+-------+-------+-------+-------+-------+ | Move1 | Move2 | Move3 | Move4 | Move5 | Move6 | Move7 | Move8 | +-------+-------+-------+-------+-------+-------+-------+-------+ | 1 | 1 | 1 | 1 | . | . | 1 | 1 | +-------+-------+-------+-------+-------+-------+-------+-------+

…应生成以下变量:

Number of sequences of 2 in the first half =0 Number of sequences of 2 in the second half =1 Number of sequences of 3 in the first half =0 Number of sequences of 3 in the second half =0 Number of sequences of >3 in the first half =1 Number of sequences of >3 in the second half = 0

关于如何继续此任务,我有两种可能的选择,但这两种选择都不会导致最终解决方案:

选项1:详细说明Nick使用字符串的策略建议(Stata: Maximum number of consecutive occurrences of the same value across variables),我连接了所有"Move*"变量,并尝试确定子字符串的起始位置:

egen test1 = concat(move*) gen test2 = subinstr(test1,"11","X",.) // find all consecutive series of length 2 选项1有几个问题: (1)它不考虑序列重叠的情况("1111"被认为是2的2个序列) (2)它缩短了生成的字符串test2,因此X的位置不再对应于test1中的起始位置 (3)如果我需要检查长度大于3的序列,则不考虑可变长度的子串。

选项2:创建一个辅助变量集,以标识某个固定预定义长度的1的连续集合的起始位置。在前面的示例的基础上,为了计算长度为2的序列,我尝试获得的是一个辅助变量集,如果序列在给定的移动时开始,则等于1,否则等于0:

+-------+-------+-------+-------+-------+-------+-------+-------+ | Move1 | Move2 | Move3 | Move4 | Move5 | Move6 | Move7 | Move8 | +-------+-------+-------+-------+-------+-------+-------+-------+ | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | +-------+-------+-------+-------+-------+-------+-------+-------+

我的代码如下所示,但当我尝试重新开始计算连续出现的事件时,它崩溃了:

quietly forval i = 1/42 { gen temprow`i' =. egen rowsum = rownonmiss(seq1-seq`i') //count number of occurrences replace temprow`i'=rowsum mvdecode seq1-seq`i',mv(1) if rowsum==2 drop rowsum }

有人知道解决这项任务的方法吗?

推荐答案

假设连接所有移动的字符串变量all(名称test1很难让人联想到)。

第一次尝试:按字面意思理解您的示例

从您的8步棋的例子来看,游戏的上半场是1-4步,下半场是5-8步。因此,对于每一半来说,只有一种方法有>3步,即有4步。在这种情况下,每个子字符串将"1111",并且计数减少到测试一种可能性:

gen count_1_4 = substr(all, 1, 4) == "1111" gen count_2_4 = substr(all, 5, 4) == "1111"

扩展此方法,只有两种方法可以按顺序进行3个动作:

gen count_1_3 = inlist(substr(all, 1, 4), "111.", ".111") gen count_2_3 = inlist(substr(all, 5, 4), "111.", ".111") 在类似的风格中,不能在游戏的每一半中有两个连续的2个移动的实例,因为这将符合4个移动的资格。因此,每半部分最多有一个2步连续移动的实例。该实例必须匹配"11."或".11"这两个模式中的任何一个。".11."是允许的,因此两者都包括。正如刚刚提到的,我们还必须排除任何与3个动作序列相匹配的错误。

gen count_1_2 = (strpos(substr(all, 1, 4), "11.") | strpos(substr(all, 1, 4), ".11") ) & !count_1_3 gen count_2_2 = (strpos(substr(all, 5, 4), "11.") | strpos(substr(all, 5, 4), ".11") ) & !count_2_3 如果找到匹配项,则每个strpos()评估的结果将为正,如果任一参数为正,则(arg1|arg2)将为真(1)。(对于Stata,非零在逻辑计算中为真。)

这在很大程度上是针对您的特定问题量身定做的,但也不会因此而变得更糟。

附注:我没有努力理解您的代码。您似乎混淆了subinstr()和strpos()。如果你想知道位置,subinstr()无能为力。

第二次尝试

您的最后一段代码暗示您的示例具有很大的误导性:如果可以有42个移动,则上面的方法无法毫无困难地扩展。你需要一种不同的方法。

假设字符串变量all可以是42个字符。我将搁置上半场和下半场之间的区别,这可以通过修改这种方法来解决。简单来说,只需将历史分为两个变量,一个用于前半部分,另一个用于后半部分,然后重复两次这种方法。

您可以通过以下方式克隆历史记录

clonevar work = all gen length1 = . gen length2 = .

并设置count变量。这里count_4将包含4个或更多的计数。

gen count_4 = 0 gen count_3 = 0 gen count_2 = 0 首先,我们寻找长度为42,...,2的移动序列。每次我们找到一个移动序列,我们就把它清空并增加计数。

qui forval j = 42(-1)2 { replace length1 = length(work) local pattern : di _dup(`j') "1" replace work = subinstr(work, "`pattern'", "", .) replace length2 = length(work) if `j' >= 4 { replace count4 = count4 + (length1 - length2) / `j' } else if `j' == 3 { replace count3 = count3 + (length1 - length2) / 3 } else if `j' == 2 { replace count2 = count2 + (length1 - length2) / 2 } }

这里的重要细节是

  • 如果我们删除一个模式(重复的实例)并测量长度的变化,我们就删除了该模式的(长度变化)/(模式的长度)实例。所以,如果我查找"11",发现长度减少了4,我只找到了两个实例。

  • 向下工作,删除我们发现的内容,确保我们不会发现误报,例如,如果删除"1111111",我们就不会发现后面包含的"111111"、"11111"、……、"11"。

  • 删除意味着我们应该在克隆上工作,以便不破坏感兴趣的内容。

  • 更多推荐

    Stata:计算预定义长度的连续出现的次数

    本文发布于:2023-11-22 06:57:36,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1616407.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:长度   次数   Stata

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!