【问题标题】:Creating data continuously using rnorm until an outlier occurs in R使用 rnorm 连续创建数据,直到 R 中出现异常值
【发布时间】:2015-09-28 01:29:17
【问题描述】:

抱歉标题令人困惑,但我不知道如何命名我正在尝试做的事情。我的目标是创建一个包含 1000 个 obs 的数据集,每个数据集都是运行的长度。我创建了一个阶段 1 数据集,从中生成了一组控制限制。我现在要做的是创建一个最有可能使用 rnorm 的阶段 2 数据集。我试图做的是创建一个重复循环,该循环将在阶段 2 数据集中不断创建值,直到其中一个值超出阶段 1 数据集产生的控制限制。例如,如果我有 3.0 和 -3.0 作为控制限制,phase2 数据集将创建一堆观察值,直到 obs 398,此时此处的值恰好是 3.45,从而停止创建数据。然后我的目标是记录数字 398。此外,我试图将代码循环回阶段 1 数据集/控制限制部分并创建一组新的控制限制,然后运行另一个阶段 2,直到我记录了 1000 个运行长度.我为阶段1/控制限制提供的代码工作正常,如下所示:

nphase1=50
nphase2=1000
varcount=1
meanshift= 0
sigmashift= 1


##### phase1 dataset/ control limits #####

phase1 <- matrix(rnorm(nphase1*varcount, 0, 1), nrow = nphase1, ncol=varcount)
mean_var <- apply(phase1, 2, mean)
std_var <- apply(phase1, 2, sd)
df_var <- data.frame(mean_var, std_var)

Upper_SPC_Limit_Method1 <- with(df_var, mean_var + 3 * std_var)
Lower_SPC_Limit_Method1 <- with(df_var, mean_var - 3 * std_var)
df_control_limits<- data.frame(Upper_SPC_Limit_Method1, Lower_SPC_Limit_Method1) 

我之前在 SAS 中创建了这段代码,它看起来像这样。可能是我试图实现的目标的更好参考,然后我试图解释它。

%macro phase2_dataset (n=,varcount=, meanshift=, sigmashift=, nphase1=,simID=,);
%do z=1 %to &n;
 %phase1_dataset (n=&nphase1, varcount=&varcount);
    data phase2; set control_limits n=lastobs;
       call streaminit(0);
       do until (phase2_var1<Lower_SPC_limit_method1_var1 or
                 phase2_var1>Upper_SPC_limit_method1_var1);
        phase2_var1 = rand("normal", &meanshift, &sigmashift); 
        output;
        end;

    run;
 ods exclude all; 
 proc means data=phase2;
 var phase2_var1;
 ods output summary=x;
 run; 
 ods select all; 
 data run_length; set x;
 keep Phase2_var1_n;
 run; 
proc append base= QA.Phase2_dataset&simID data=Run_length force; run;    
%end;
%mend; 

还一直在研究使用 while 循环代替重复循环。 我是 R 新手,因此非常感谢您提出的任何想法。谢谢!

【问题讨论】:

    标签: r while-loop repeat


    【解决方案1】:

    使用 while 循环确实似乎是要走的路。这就是我认为您正在寻找的内容:

    set.seed(10) #Making results reproducible
    
    replicate(100, { #100 is easier to display here
      phase1 <- matrix(rnorm(nphase1*varcount, 0, 1), nrow = nphase1, ncol=varcount)
      mean_var <- colMeans(phase1) #Slightly better than apply
      std_var <- apply(phase1, 2, sd)
      df_var <- data.frame(mean_var, std_var)
    
      Upper_SPC_Limit_Method1 <- with(df_var, mean_var + 3 * std_var)
      Lower_SPC_Limit_Method1 <- with(df_var, mean_var - 3 * std_var)
      df_control_limits<- data.frame(Upper_SPC_Limit_Method1, Lower_SPC_Limit_Method1)
    
      #Phase 2
    
      x <- 0
      count <- 0
    
      while(x > Lower_SPC_Limit_Method1 && x < Upper_SPC_Limit_Method1) {
        x <- rnorm(1)
        count <- count + 1
      }
      count
    })
    

    结果是:

      [1]  225   91   97  118  304  275  550   58  115    6  218   63  176  100  308  844   90 2758
     [19]  161  311 1462  717 2446   74  175   91  331  210  118 1517  420   32   39  201  350   89
     [37]   64  385  212    4   72  730  151    7 1159   65   36  333   97  306  531 1502   26   18
     [55]   67  329   75  532   64  427   39  352  283  483   19    9    2 1018  137  160  223   98
     [73]   15  182   98   41   25 1136  405  474 1025 1331  159   70   84  129  233    2   41   66
     [91]    1   23    8  325   10  455  363  351  108    3
    

    如果性能成为问题,探索一些改进可能会很有趣,例如一次使用rnorm() 创建更多数字,然后计算需要多少才能超过限制并在必要时重复。

    【讨论】:

    • 这就是我一直想做的,谢谢。快速跟进,为了保存这些结果的数据框,我可以在复制之前添加类似 DF_ARL
    • 是的,虽然我不明白你为什么要将它保存为单列 data.frame。如果您还有另一列要添加,您当然可以在之后从中创建一个数据框。
    • 我可能没有完全理解,但while 循环似乎非常低效。可能需要数千次抽奖才能找到超出限制的内容。相反,您应该在 [0,F^-1(Lower_limit)]U[F^-1(Upper_limit),1] 上绘制一个变量 uniform,其中 F 是标准的普通 CDF(例如,将 U(0,1) 绘制乘以 F^-1(Lower)+1-F^-1(Upper))。
    • @MichaelChirico 我同意while 可能非常低效,特别是如果将限制更改为更大的范围(尽管在某些时候如果不调整rnorm 的平均值和标准差是不可能的)。也许你可以发布你的解决方案?我很想看到这样做的聪明数学方法。
    • @MichaelChirico 你真的不应该在别人的答案中编辑代码。如果您觉得有什么需要解决的,您可以在 cmets 中这样做,但您的修改不应该被批准。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 2020-04-11
    • 1970-01-01
    • 2018-03-05
    相关资源
    最近更新 更多