Stata 当前值等于或小于前90天值的计数事件

Stata 当前值等于或小于前90天值的计数事件,stata,Stata,我有一个带有间隙的每日事务数据集。我想看看在T日参考价格websiteprice为$X的产品在之前T-90天内是否有至少10%的实际售价actualsoldprice$Y>=$X。换句话说,对于sale_at_或_over_refprice==1的每笔交易,我们需要计算在过去90天内(给定产品)先前交易的实际售价达到或超过该交易参考价格的多少倍 我在wanted变量中包含了我正在寻找的第一步结果 我的数据如下: * Example generated by -dataex-. For more

我有一个带有间隙的每日事务数据集。我想看看在T日参考价格
websiteprice
为$X的产品在之前T-90天内是否有至少10%的实际售价
actualsoldprice
$Y>=$X。换句话说,对于
sale_at_或_over_refprice
==1的每笔交易,我们需要计算在过去90天内(给定产品)先前交易的实际售价达到或超过该交易参考价格的多少倍

我在
wanted
变量中包含了我正在寻找的第一步结果

我的数据如下:

* Example generated by -dataex-. For more info, type help dataex
clear
input str9 orderdate str16 productcode str10 productcategory byte(websiteprice actualsoldprice sale_at_or_above_refprice var7 wanted)
"3-Jan-20"  "MZZ32819-564-282" "Mens Jeans" 40 25 . .  .
"8-Jan-20"  "MZZ32819-564-282" "Mens Jeans" 40 40 1 .  .
"12-Jan-20" "MZZ32819-564-282" "Mens Jeans" 40 40 1 .  1
"12-Sep-20" "MZZ32819-564-282" "Mens Jeans" 40 28 . .  .
"18-Sep-20" "MZZ32819-564-282" "Mens Jeans" 40 24 . .  .
"20-Sep-20" "MZZ32819-564-282" "Mens Jeans" 50 30 . .  .
"27-Sep-20" "MZZ32819-564-282" "Mens Jeans" 50 25 . .  .
"11-Oct-20" "MZZ32819-564-282" "Mens Jeans" 40 20 . .  .
"19-Oct-20" "MZZ32819-564-282" "Mens Jeans" 35 24 . .  .
"2-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 20 20 1 .  6
"2-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 14 14 1 .  7
"4-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 14 14 1 .  8
"7-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 14 14 1 .  9
"7-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 20 20 1 .  7
"9-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 20 20 1 .  8
"11-Nov-20" "MZZ32819-564-282" "Mens Jeans" 14 14 1 . 12
"12-Nov-20" "MZZ32819-564-282" "Mens Jeans" 14 14 1 . 13
"14-Nov-20" "MZZ32819-564-282" "Mens Jeans" 14 14 1 . 14
"15-Nov-20" "MZZ32819-564-282" "Mens Jeans" 14 14 1 . 15
"18-Nov-20" "MZZ32819-564-282" "Mens Jeans" 14 14 1 . 16
"24-Nov-20" "MZZ32819-564-282" "Mens Jeans" 20 20 1 .  9
end
编辑-我已更新了
wanted
变量,并包含了
new\u wanted
。这一差异考虑到了具有多种价格的重复日期。还包括2个按id运行此流程的产品

* Example generated by -dataex-. For more info, type help dataex
clear
input str9 orderdate str16 productcode str10 productcategory byte(websiteprice actualsoldprice sale_at_or_above_refprice wanted new_wanted)
"3-Jan-20"  "MZZ32819-564-282" "Mens Jeans" 40 25 .  .  .
"8-Jan-20"  "MZZ32819-564-282" "Mens Jeans" 40 40 1  0  0
"12-Jan-20" "MZZ32819-564-282" "Mens Jeans" 40 40 1  1  1
"12-Sep-20" "MZZ32819-564-282" "Mens Jeans" 40 28 .  .  .
"18-Sep-20" "MZZ32819-564-282" "Mens Jeans" 40 24 .  .  .
"20-Sep-20" "MZZ32819-564-282" "Mens Jeans" 50 30 .  .  .
"27-Sep-20" "MZZ32819-564-282" "Mens Jeans" 50 25 .  .  .
"11-Oct-20" "MZZ32819-564-282" "Mens Jeans" 40 20 .  .  .
"19-Oct-20" "MZZ32819-564-282" "Mens Jeans" 35 24 .  .  .
"2-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 20 20 1  6  6
"2-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 14 14 1  6  6
"4-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 14 14 1  8  7
"7-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 14 14 1  9  8
"7-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 20 20 1  7  7
"9-Nov-20"  "MZZ32819-564-282" "Mens Jeans" 20 20 1  8  9
"11-Nov-20" "MZZ32819-564-282" "Mens Jeans" 14 14 1 12 10
"12-Nov-20" "MZZ32819-564-282" "Mens Jeans" 14 14 1 13 11
"14-Nov-20" "MZZ32819-564-282" "Mens Jeans" 14 14 1 14 12
"15-Nov-20" "MZZ32819-564-282" "Mens Jeans" 14 14 1 15 13
"18-Nov-20" "MZZ32819-564-282" "Mens Jeans" 14 14 1 16 14
"24-Nov-20" "MZZ32819-564-282" "Mens Jeans" 20 20 1  9  9
"6-Jan-20"  "ADDZ4449-524-645" "Mens Bags"  60 50 .  .  .
"11-Jan-20" "ADDZ4449-524-645" "Mens Bags"  70 60 .  .  .
"12-Feb-20" "ADDZ4449-524-645" "Mens Bags"  60 60 1  .  1
"12-Jul-20" "ADDZ4449-524-645" "Mens Bags"  60 50 .  .  .
"18-Sep-20" "ADDZ4449-524-645" "Mens Bags"  50 55 1  .  1
"20-Sep-20" "ADDZ4449-524-645" "Mens Bags"  50 45 .  .  .
"20-Sep-20" "ADDZ4449-524-645" "Mens Bags"  66 45 .  .  .
"12-Oct-20" "ADDZ4449-524-645" "Mens Bags"  55 60 1  .  1
"19-Oct-20" "ADDZ4449-524-645" "Mens Bags"  60 60 1  .  1
"2-Nov-20"  "ADDZ4449-524-645" "Mens Bags"  70 73 1  .  0
"2-Nov-20"  "ADDZ4449-524-645" "Mens Bags"  60 56 .  .  .
"4-Nov-20"  "ADDZ4449-524-645" "Mens Bags"  60 60 1  .  3
"7-Nov-20"  "ADDZ4449-524-645" "Mens Bags"  50 45 .  .  .
"7-Nov-20"  "ADDZ4449-524-645" "Mens Bags"  66 66 1  .  1
"9-Nov-20"  "ADDZ4449-524-645" "Mens Bags"  60 56 .  .  .
"11-Nov-20" "ADDZ4449-524-645" "Mens Bags"  60 76 1  .  5
"12-Nov-20" "ADDZ4449-524-645" "Mens Bags"  60 71 1  .  6
"13-Nov-20" "ADDZ4449-524-645" "Mens Bags"  60 26 .  .  .
"15-Nov-20" "ADDZ4449-524-645" "Mens Bags"  65 70 1  .  4
"15-Nov-20" "ADDZ4449-524-645" "Mens Bags"  67 70 1  .  3
"22-Nov-20" "ADDZ4449-524-645" "Mens Bags"  56 70 1  .  9
end
下面是我试图适应此任务的代码。STATALIST将此归功于Ken Chui

gen date1 = date(orderdate, "DMY", 2020)
format date1 %td

local max = _N
gen wanted2 = .
foreach x of numlist 1/`max'{
    capture drop get get_sum
    gen get = actualsoldprice >= actualsoldprice[`x']
    rangestat (sum) get, interval(date -90 -1)
    replace wanted2 = get_sum if _n == `x'
}
replace wanted2 = . if sale_at_or_above_refprice == .
*首先将日期转换为Stata日期
gen stata_日期=日期(订单日期,“DM20Y”)
格式stata_日期%td
*在while循环中,将数据和产品代码作为停止条件进行排序,同时希望对它们进行排序
排序产品代码stata_日期
*创建变量以存储结果
gen count_less=。
*在所有行上循环
计数
forvalue行=1/`r(N)'{
*仅适用于
如果销售价格高于参考价格[`row']==1{
*将此行的结果变量设置为0
如果_n=='row',则替换count\u less=0
*while循环中使用的初始化局部变量
局部真=1
本地行_skip=1
本地计数=0
本地最后日期=统计日期[`row']
*循环,直到任何停止条件将local true设置为0
而'true'==1{
*测试行跳过是否命中数据集的顶部(即第0行)
如果'row'-'row_skip'==0,则本地true=0
*测试比较行中的产品是否相同
如果productcode[`row']!=productcode[`row'-`row_skip']local true=0,则为else
*测试之前的订单是否在90天内
否则,如果stata_date[`row']-stata_date[`row'-`row_skip']>90 local true=0
*测试实际旧价格是否低于旧网站价格

如果网站价格[`row']如果您有数百万次观察,此解决方案可能无法很好地扩展,但尽管速度较慢,但它仍应能完成此工作。非常感谢!我认为第2行的通缉价格应为0,而第3行的通缉价格应为1。原因是第2行的网站价格为40,之前注明日期的实际价格低于40。0来自于它仍然是一个sale_at_或_over_refprice==1,但之前没有更低的值(90天)。让我知道这是否有意义。此外,我忘了指出11月2日和11月7日的双重情况需要协调,而不是作为单独的一天出现。我已更新了我的答案,因此现在第2行和第3行的计数相同。然后可以运行
collapse(sum)按(统计日期)进行的无计数
获取所有天数的总和。如果您需要这些数据和原始数据,您可以将
折叠的结果与原始数据合并。如果这解决了您的问题,请向上投票并接受答案。虽然循环观察似乎是悲观的,但我注意到我尝试了使用SSC的
rangerun
直接路线,但没有得出结论ded说我对数据的理解不够透彻,无法提出积极的建议。交叉发布和回答被广泛认为是礼貌的,告诉人们交叉发布。即使在修改数据的例子中,同一产品在同一天的网站价格怎么可能不同?我想这意味着价格在给定的一天发生了变化,但事实并非如此如果没有额外的细节,很难理解此类数据。也就是说,有一个超出每日日期的时间顺序。或者这个示例也是错误的。这是一个很难回答的问题。您已经给出了一个示例数据集(谢谢),它很难理解(不是很好),并且没有显示任何试图自己解决问题的代码(同上)@NickCox为没有披露更多信息表示歉意。初始数据是客户交易列表。我修改数据集以简化我试图完成的任务。您看到的是每天产品的一组价格。重复的日期表示特定产品在同一天以不同的价格出售。我更新了我的问题,并将在找到解决方案后继续进行更改。显然问题在于数据。感谢您的解释。
*Start by converting date to Stata date
gen stata_date = date(orderdate,"DM20Y")
format stata_date %td

*Sort data and product code as stop conditions in while loop expect them to be sorted
sort productcode stata_date

*Create varialbe to store result
gen count_less = .

*Loop over all rows
count 
forvalue row = 1/`r(N)' {
    
    *Only applicable to 
    if sale_at_or_above_refprice[`row'] == 1 {
        
        *Set result variable to 0 for this row
        replace count_less = 0 if _n == `row'
        
        *Initate locals used in while loop
        local true = 1
        local row_skip = 1
        local count = 0
        local last_date = stata_date[`row']
        
        *Loop until any stop condition sets local true to 0
        while `true' == 1 {
           
            *Test if row_skip hits top of data set (i.e row 0)
            if `row'-`row_skip' == 0                                        local true = 0
            *Test that product is same in compare row
            else if productcode[`row'] != productcode[`row'-`row_skip']     local true = 0
            *Test that previous order is within 90 days
            else if stata_date[`row'] - stata_date[`row'-`row_skip'] > 90   local true = 0

            *Test if actualsoldprice is less thatn old websiteprice
            else if websiteprice[`row'] <= actualsoldprice[`row'-`row_skip'] {
                
                * Each date can only be counted once, so test if date is last date counted 
                if `last_date' != stata_date[`row'-`row_skip'] {
                    *Compare row fits condition, add 1 to counter
                    local count = `count' + 1   
                    
                    *Update last counted date
                    local last_date = stata_date[`row'-`row_skip']
                }
            }
            *Skip one more prevuous row
            local row_skip = `row_skip' + 1
        }
        *Add the count result to the result varaible for this row
        replace count_less = `count' if _n == `row'
    }
}