删除汇总时间序列中的观察结果

时间:2013-07-06 22:28:16

标签: r dataframe sas split-apply-combine

我有一个垂直排列(堆叠)的汇集时间序列data.frame,如下所示:

date    item    qty_sold
day_1   orange  0
day_2   orange  0
day_3   orange  0
day_4   orange  0
day_5   orange  5
day_6   orange  0
day_7   orange  8
day_8   orange  0
day_1   hammer  0
day_2   hammer  0
day_3   hammer  3
day_4   hammer  0
day_5   hammer  70
day_6   hammer  70
day_7   hammer  0
Day_8   hammer  80

在每个“项目”的子系列/子组中,我需要在观察到第一个正qty_sold的那天之前识别并删除所有观察*。例如,对于“ orange ”系列,这意味着要确定第1天到第4天,对于“”系列,这意味着要在前2天内完成。


(如果上述说明不清楚): 从数据集中的每个子系列,我需要删除从date = Day_1到date = Day_k的所有日期,这样对于区间1 ... k qty_sold = 0中的每一天,AND保留所有日期的行= Day_k + 1 qty_sold> = 0)

有人可以就如何解决这个问题提出一个想法吗?实际数据集包含大约一百万行。我也欢迎使用SAS除R之外的建议。

2 个答案:

答案 0 :(得分:3)

我完全赞同@joran在那里的观点。我会在这里给出(n)(R)答案,即使这个问题没有显示出任何研究成果。对于未来,请向我们展示您尝试过的代码。

对于您的问题,第一步是使用基本功能或一个很好的包,它可以帮助您split data.frameapplycombine您想要的任何功能应用于每个拆分组并split-apply-combine结果(通常称为plyr策略)。有几个不错的(外部)包,即data.tabledata.table。虽然,我更喜欢data.frame data.frame - 类似操作,因为它通常要快得多。

首先,我们会将您的data.table转换为install.packages("data.table")。如果您没有安装此软件包,则可以执行require(data.table) # load package dt <- data.table(df) # convert data.frame to data.table

data.table

现在,要将by拆分成组,我们可以在data.table中使用参数apply。我们的cummax函数将为dt[, .SD[cummax(qty_sold) > 0], by = item] item date qty_sold 1: orange day_5 5 2: orange day_6 0 3: orange day_7 8 4: orange day_8 0 5: hammer day_3 3 6: hammer day_4 0 7: hammer day_5 70 8: hammer day_6 70 9: hammer day_7 0 10: hammer Day_8 80 ,因为这只会为您的第一个连续零和非零后的0提供0(如果您的数据中没有负值,我假设这里)。然后,结果自动组合。所以,让我们这样做:

require(data.table)
dt <- data.table(df)
dt[, .SD[cummax(qty_sold)>0], by = item]

总结一下:

by = item

有关语法的更多解释。我们先考虑split。这是item内部data.table为您提供的数据的部分(即,item= orange的整个item = hammer将被视为第一个,后面是.SD[cummax(qty_sold) > 0]的部分{1}}等等。)

中间部分apply是神奇发生的地方 - .SD等效函数。在这里,item只是拆分部分(对应于.SD一次采取一个部分。为了更清楚地了解每次dt[, print(.SD), by = item]中的内容,请执行:{{1}}。

这基本上会删除在开始时具有连续0的行并保留其他所有内容(只要没有负值,解决方案就会得到保证)。

答案 1 :(得分:2)

SAS方法类似于:跟踪保留变量是否已经遇到项目的正值。如果没有,则不输出。如果是,请在用于跟踪它的变量中记下它。在项目的最后一行之后,重置您的跟踪变量。 例如:(必要时排序)

data RESULT (drop=found_first_positive);
    set DATASET;
    by item date;
    retain found_first_positive 0;
    if quantity>0 then found_first_positive=1;
    if found_first_positive;
    if last.item then found_first_positive=0;
run;