1

Rに次のデータフレームがあります:

df <- data.frame(id=c('a','b','a','c','b','a'),
                 indicator1=c(1,0,0,0,1,1),
                 indicator2=c(0,0,0,1,0,1),
                 extra1=c(4,5,12,4,3,7),
                 extra2=c('z','z','x','y','x','x'))

id indicator1 indicator2 extra1 extra2
a          1          0      4      z
b          0          0      5      z
a          0          0     12      x
c          0          1      4      y
b          1          0      3      x
a          1          1      7      x

特定の ID が 1 に等しいさまざまなインジケーターを表示する回数のすべての行のカウントを持つ新しい列を追加したいと思います。例:

id indicator1 indicator2 extra1 extra2 countInd1 countInd2 countInd1Ind2
a          1          0      4      z      2         1           1
b          0          0      5      z      1         0           0
a          0          0     12      x      2         1           1
c          0          1      4      y      0         1           0
b          1          0      3      x      1         0           0
a          1          1      7      x      2         1           1

これどうやってするの?

4

2 に答える 2

4

いくつかの方法があります。aveと を使用したものを次に示しwithinます。

within(df, {
  ind1ind2 <- ave(as.character(interaction(indicator1, indicator2, drop=TRUE)), 
                  id, FUN = function(x) sum(x == "1.1"))
  ind2 <- ave(indicator2, id, FUN = function(x) sum(x == 1))
  ind1 <- ave(indicator1, id, FUN = function(x) sum(x == 1))
})
#   id indicator1 indicator2 extra1 extra2 ind1 ind2 ind1ind2
# 1  a          1          0      4      z    2    1        1
# 2  b          0          0      5      z    1    0        0
# 3  a          0          0     12      x    2    1        1
# 4  c          0          1      4      y    0    1        0
# 5  b          1          0      3      x    1    0        0
# 6  a          1          1      7      x    2    1        1

代替案は次のとおりです。

A <- setNames(aggregate(cbind(indicator1, indicator2) ~ id, df, 
                        function(x) sum(x == 1)), c("id", "ind1", "ind2"))
B <- setNames(aggregate(interaction(indicator1, indicator2, drop = TRUE) ~ id, 
                        df, function(x) sum(x == "1.1")), c("id", "ind1ind2"))
Reduce(function(x, y) merge(x, y), list(df, A, B))
#   id indicator1 indicator2 extra1 extra2 ind1 ind2 ind1ind2
# 1  a          1          0      4      z    2    1        1
# 2  a          0          0     12      x    2    1        1
# 3  a          1          1      7      x    2    1        1
# 4  b          0          0      5      z    1    0        0
# 5  b          1          0      3      x    1    0        0
# 6  c          0          1      4      y    0    1        0

もちろん、データが大きい場合は、「data.table」パッケージを調べてください。withinまた、バージョンよりもタイピングが少し少なくなります。

library(data.table)
DT <- data.table(df)
DT[, c("ind1", "ind2", "ind1ind2") := 
     list(sum(indicator1 == 1),
          sum(indicator2 == 1),
          sum(interaction(indicator1, indicator2, 
                          drop = TRUE) == "1.1")),
   by = "id"]
DT
#    id indicator1 indicator2 extra1 extra2 ind1 ind2 ind1ind2
# 1:  a          1          0      4      z    2    1        1
# 2:  b          0          0      5      z    1    0        0
# 3:  a          0          0     12      x    2    1        1
# 4:  c          0          1      4      y    0    1        0
# 5:  b          1          0      3      x    1    0        0
# 6:  a          1          1      7      x    2    1        1

また、 の代わりに、それがより明確であると思われる場合sum(interaction(...) == "1.1")は、それを行うこともできます。sum(indicator1 == 1 & indicator2 == 1)どちらがより効率的かを確認するためのベンチマークは行っていません。interaction最初に頭に浮かんだことです。

于 2013-08-20T17:07:06.233 に答える