【问题标题】:R Example - ddply, ave, and mergeR 示例 - ddply、ave 和 merge
【发布时间】:2013-11-10 16:30:28
【问题描述】:

我写了一个代码。如果你们能提出更好的方法来做我想做的事情,那就太好了。 dt 给出如下:

   SIC FYEAR AU       AT
1    1  2003  6  212.748
2    1  2003  5 3987.884
3    1  2003  4  100.835
4    1  2003  4 1706.719
5    1  2003  5    9.159
6    1  2003  7   60.069
7    1  2003  5  100.696
8    1  2003  4  113.865
9    1  2003  6  431.552
10   1  2003  7  309.109 ...

我的工作是为给定的 SIC 和 FYEAR 创建一个新列,其中 AT 百分比最高的 AU 以及最高 AT 与第二高 AT 之间的差值为 1,否则为 0。这是我的尝试做提到的事情。

a <- ddply(dt,.(SIC,FYEAR),function(x){ddply(x,.(AU),function(x) sum(x$AT))});

   SIC FYEAR AU        V1
1    1  2003  4  3412.619
2    1  2003  5 13626.241
3    1  2003  6   644.300
4    1  2003  7  1478.633
5    1  2003  9     0.003
6    1  2004  4  3976.242
7    1  2004  5  9383.516
8    1  2004  6   457.023
9    1  2004  7   456.167
10   1  2004  9   238.282

其中 V1 表示给定 SIC 和 FYEAR 的给定 AU 的所有行的总和。接下来我做:

a$V1 <- ave(a$V1, a$SIC, a$FYEAR, FUN = function(x) x/sum(x));

   SIC FYEAR AU           V1
1    1  2003  4 1.780949e-01
2    1  2003  5 7.111150e-01
3    1  2003  6 3.362420e-02
4    1  2003  7 7.716568e-02
5    1  2003  9 1.565615e-07
6    1  2004  4 2.740114e-01
7    1  2004  5 6.466382e-01
8    1  2004  6 3.149444e-02
9    1  2004  7 3.143545e-02
10   1  2004  9 1.642052e-02

V1 列现在表示每个 AU 对给定 SIC 和 FYEAR 的 AT 贡献的百分比值。接下来,

a$V2 <- ave(a$V1, a$SIC, a$FYEAR, FUN = function(x) {t<-((sort(x, TRUE))[2]); 
                                                    ifelse((x-t)> 0.1,1,0)});

   SIC FYEAR AU           V1 V2
1    1  2003  4 1.780949e-01  0
2    1  2003  5 7.111150e-01  1
3    1  2003  6 3.362420e-02  0
4    1  2003  7 7.716568e-02  0
5    1  2003  9 1.565615e-07  0
6    1  2004  4 2.740114e-01  0
7    1  2004  5 6.466382e-01  1
8    1  2004  6 3.149444e-02  0
9    1  2004  7 3.143545e-02  0
10   1  2004  9 1.642052e-02  0

给定 SIC 的 AU,以及对 AT 贡献百分比最高的 FYEAR,如果差异大于 10%,则 AU 为 1,否则为 0。

然后我将结果与原始数据 dt 合并。

dt <- merge(dt,a,key=c("SIC","FYEAR","AU"));

   SIC FYEAR AU       AT           V1 V2
1    1  2003  4 1706.719 1.780949e-01  0
2    1  2003  4  100.835 1.780949e-01  0
3    1  2003  4  113.865 1.780949e-01  0
4    1  2003  4 1491.200 1.780949e-01  0
5    1  2003  5 3987.884 7.111150e-01  1
6    1  2003  5  100.696 7.111150e-01  1
7    1  2003  5   67.502 7.111150e-01  1
8    1  2003  5 9461.000 7.111150e-01  1
9    1  2003  5    9.159 7.111150e-01  1
10   1  2003  6  212.748 3.362420e-02  0

我做的很麻烦。有没有更好的方法来做同样的事情?谢谢。

【问题讨论】:

  • 你可以使用包,对繁琐的语法不满意,当你看到更好的选项时你不喜欢它,因为它使用包?笏? @Arun imo,您应该取消删除您的答案-如果 OP 之后出于某种原因想要回到 data.frame,我看不出是什么阻止了他们。
  • 我是 R 新手。而且我想掌握基本的 R,因此不想将数据表用于我的目的,即使我的数据大小超过 70k 行和 40 列。我相信数据表对我来说会更快,但我会坚持使用数据框来获得 R 的专业知识。
  • 您确实意识到ddply 不是基本的R,对吧?不管怎样,对他们自己来说,只是指出你的逻辑没有意义。
  • 我必须说我真的很努力理解你的意思。您的示例是不完整的,因为我没有看到所有数据并且无法验证我自己的代码。但是,我确实认为您的问题一旦正确定义,就可以在基本的 R 中相当简单地解决。但我不能确定,也不能告诉你,在我更好地理解你的目标、查看更完整的示例并至少了解上下文之前,我是如何做到的。

标签: r dataframe plyr


【解决方案1】:

我不确定删除的答案是否与此相同,但您可以在几行内有效地完成。

# Simulate data
set.seed(1)
n<-1000
dt<-data.frame(SIC=sample(1:10,n,replace=TRUE),FYEAR=sample(2003:2007,n,replace=TRUE),
AU=sample(1:7,n,replace=TRUE),AT=abs(rnorm(n)))

# Cacluate proportion.
dt$prop<-ave(dt$AT,dt$SIC,dt$FYEAR,FUN=prop.table)
# Find AU with max proportion.
dt$au.with.max.prop<-
  ave(dt,dt$SIC,dt$FYEAR,FUN=function(x)x$AU[x$prop==max(x$prop)])[,1]

一切都在基地,避免merge,所以它不会那么慢。

【讨论】:

    【解决方案2】:

    这是一个使用data.table的版本:

    require(data.table)
    DT <- data.table(your_data_frame)
    setkey(DT, SIC, FYEAR, AU)
    DT[setkey(DT[, sum(AT), by=key(DT)][, V1 := V1/sum(V1), 
              by=list(SIC, FYEAR)])[, V2 := (V1 - V1[.N-1] > 0.1) * 1, 
              by=list(SIC, FYEAR)]]
    

    DT[, sum(AT), by=key(DT)][, V1 := V1/sum(V1), by=list(SIC, FYEAR)] 部分首先将所有三列的 AT 相加,然后通过引用将列 SIC, FYEAR 的 V1 替换为 V1/sum(V1)。包装此代码的setkey 对所有四列进行排序。因此,最后一个值将始终是第二高的值(在没有重复值的情况下)。使用它,我们可以通过引用将V2 创建为:[, V2 := (V1 - V1[.N-1] &gt; 0.1) * 1, by=list(SIC, FYEAR)]]。完成此操作后,我们可以使用 DT[.] 执行 join

    希望这会有所帮助。

    【讨论】:

    • 我正在寻找数据框不转换为数据表的解决方案。对纯数据框解决方案感兴趣。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    • 2017-12-02
    相关资源
    最近更新 更多