【问题标题】:Find first non-zero occurrence in dataframe在数据框中查找第一个非零出现
【发布时间】:2012-12-10 05:00:26
【问题描述】:

我有一个按帐户 ID 划分的销售时间序列。为了计算平均增长,我需要为每个 ID 提取非零销售额的第一个月。由于帐户可能是在不同时间建立的,因此我需要动态识别帐户中销售额首次> 0 的时间。

该行的索引足以让我传递给计算增长的函数。因此,我希望通过帐户 ID 得到以下结果:

54 - [1]
87 - [4]
95 - [2]

I tried `apply(df$Sales,2,match,x>0)`  but this doesn't work.

有什么建议吗?或者,有没有更简单的方法来使用这个数据集计算 CAGR?

提前致谢!

CalendarMonth   ID  Sales
8/1/2008    54  6692.60274
9/1/2008    54  6476.712329
10/1/2008   54  6692.60274
11/1/2008   54  6476.712329
12/1/2008   54  11098.60822
7/1/2008    87  0
8/1/2008    87  0
9/1/2008    87  0
10/1/2008   87  18617.94155
11/1/2008   87  18017.36279
12/1/2008   87  18617.94155
1/1/2009    87  18617.94155
2/1/2009    87  16816.20527
7/1/2008    95  0
8/1/2008    95  8015.956284
9/1/2008    95  0
10/1/2008   95  8015.956284
11/1/2008   95  6309.447514
12/1/2008   95  6519.762431
1/1/2009    95  6519.762431

【问题讨论】:

  • 您是说要在销售额非零的 ID 条目子集中对该行的索引吗?因为 87 的 4 仅当您将此表子集时,否则它将是 9(从顶部计数)。
  • 是的,没错。我还没有完全弄清楚如何,但使用 plyr 和 ggplot,我有研究 ID 子集的愿景,以有效地计算和显示平均增长统计数据。

标签: r


【解决方案1】:

这会有帮助吗:

tapply(df$Sales, df$ID, function(a)head(which(a>0),1))

df 上面的数据框在哪里?

如果您想要整行而不只是索引,这可能会有所帮助:

lapply(unique(df$ID),function(a) head(subset(df,ID==a & Sales>0),1))

【讨论】:

  • 我编辑并用列名(ID、Sales)替换了您的硬编码索引(2、3)。使用索引不太可靠。 (想象一下数据来自一个文件,而有人决定插入一列)。
  • 现在这与@digEmAll 的答案非常接近。唯一的区别是,通过使用head,如果ID 没有非零销售,您最终会得到一个列表,而他仍然会得到一个向量,但使用NA
  • 非常感谢@flodel。我想我们几乎同时回答了...... :-) 非常感谢您的编辑。在 R 控制台上从我的试验中复制时,我应该更加小心。
  • 感谢大家的回复!该建议有效,但我无法达到我的目标。如何从返回的向量中提取索引以便读取 Sales 和 CalendarMonth?还是我问错了?我只需要第一个销售额和日历月份,这样我就可以对它们运行数字操作。对不起,如果这些是新手问题,因为我很困惑:(
  • 那么您的预期结果与原始问题中所述的不同。这就是为什么我想知道您是想要请求的相对索引还是绝对索引...
【解决方案2】:

这是一个可能的解决方案:

res1 <- tapply(df$Sales,INDEX=df$ID,FUN=function(x) which(x > 0)[1])

> res1
54 87 95 
 1  4  2 

其中res 是一个数字向量,带有:

> names(res)
[1] "54" "87" "95"

如果您想在原始data.frame 中而不是子集中获取行的索引,您可以这样做:

res2 <- tapply(1:nrow(df),
              INDEX=df$ID,FUN=function(idxs) idxs[df[idxs,'Sales'] > 0][1])

> res2
54 87 95 
 1  9 15 

然后您可以简单地使用res2 中的索引来子集data.frame

df2 <- df[res2,]

> df2 
CalendarMonth   ID      Sales
  8/1/2008      54     6692.603
 10/1/2008      87    18617.942
  8/1/2008      95     8015.956

【讨论】:

  • 谢谢。这看起来很有希望!我会试一试。
【解决方案3】:

digEmAll 答案的基础上,使用functional 编程的解决方案(可能更简洁):

> res3 <- tapply(
  1:nrow(df)
  , df$ID
  , function(Idx) Idx[Position(function(x) df[x, "Sales"] > 0, Idx)]
)
> identical(res3, res2)
[1] TRUE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    相关资源
    最近更新 更多