骨料?列中的值(基于来自另一个表的行的整个列表)重复进行,其中列名与第二个表匹配

时间:2018-12-21 22:19:56

标签: r dplyr sum aggregate

罗Word的标题...但不确定如何描述。 从最基本的意义上讲,我认为我正在尝试进行汇总,但似乎这是一个汇总循环? (这将我引到了这里,因为我读到的所有内容都没有在R中使用循环。)

我有两个数据框:

df1
ID  ID2  Ball  Ball  Ball  Square  Square  Triangle  Triangle  Triangle
1   a    1     1     0     0       0       1          1         0
1   b    0     1     0     1       1       1          0         1
2   a    1     1     0     0       0       1          1         0
3   a    1     0     1     1       0       0          1         0
3   b    0     1     1     1       1       0          1         1
4   b    0     1     1     1       1       0          1         1
5   a    1     0     1     1       0       0          1         0
5   b    0     0     0     1       1       1          1         1
6   a    0     0     1     1       0       1          1         1
6   b    0     0     0     0       1       1          1         0
7   b    0     1     0     1       1       0          1         1

df2
ID  ID2  Type
1   a    Ball
1   b    Triangle
2   a    Triangle
3   a    Square
3   b    Ball
4   b    Square
5   a    Ball
5   b    Square
6   a    Ball
6   b    Triangle
7   b    Ball

这些都是通用值。 ID要复杂得多,而不是数字,数据结构是几百列乘以30,000行。

我要尝试做的是仅基于df2中的ID类型与df1中的列标题相匹配的地方来汇总列。但是我有相同的列名,这让我有点困惑。

对于此设置,我想要的输出将是:

df3
    Ball  Ball  Ball  Square  Square  Triangle  Triangle  Triangle
Sum 2     3     3     3       2       3         2         1

每列仅根据匹配的ID求和。因此,任何名为Ball的列都只汇总与df2中列出的ID 1、5和7相匹配的行。 (每种类型均如此。)

最终我想创建第二个表,将第一个表折叠为简单的平均值:

df4
Ball  Square  Triangle
2.67    2.50     2.00   

我希望这有道理!由此将创建两个数据帧。

编辑:我已经编辑了数据集以包括第二个ID,以及扩展的df2以说明其行比df1的列多。 df2中的类型不是df1中1对1匹配项。 df1中的列标题用于分配整个数据集所属的组类型。

1 个答案:

答案 0 :(得分:1)

尝试一下:

Type <- as.character(df2$Type)

ag <- sapply(2:ncol(df1), function(i) sum(df1[[i]] * (Type == names(df1)[i])))
tapply(ag, names(df1)[-1], mean)
##     Ball   Square Triangle 
## 2.000000 2.500000 1.333333 

Type <- as.character(df2$Type)
nms <- names(df1)[-1]

ag <- mapply(function(x, nm) sum(x * (Type == nm)), df1[-1], nms)
tapply(ag, nms, mean)
##     Ball   Square Triangle 
## 2.000000 2.500000 1.333333 

或:

nms <- names(df1)[-1]
Type <- as.character(df2$Type)

ag <- colSums(df1[-1] * outer(Type, nms, "=="))
tapply(ag, nms, mean)
##     Ball   Square Triangle 
## 2.000000 2.500000 1.333333 

注意

可复制形式的输入:

Lines1 <- "
ID  Ball  Ball  Ball  Square  Square  Triangle  Triangle  Triangle
1   1     1     0     0       0       1          1         0
2   0     1     0     1       1       1          0         1
3   1     1     0     0       0       1          1         0
4   1     0     1     1       0       0          1         0
5   0     1     1     1       1       0          1         1
6   0     1     1     1       1       0          1         1
7   1     0     1     1       0       0          1         0
8   0     0     0     1       1       1          1         1"
df1 <- read.table(text = Lines1, header = TRUE, check.names = FALSE)

Lines2 <- "
ID   Type
1    Ball
2    Triangle
3    Triangle
4    Square
5    Ball
6    Square
7    Ball
8    Square"
df2 <- read.table(text = Lines2, header = TRUE)