我有一个如下所示的数据集:
Person Team
1 30
2 30
3 30
4 30
11 40
22 40
1 50
2 50
3 50
4 50
15 60
16 60
17 60
1 70
2 70
3 70
4 70
11 80
22 80
我的总体目标是组织团队识别码,以便轻松查看哪些团队彼此重复以及哪些团队是唯一的。我想总结数据,看起来像这样:
Team Duplicate1 Duplicate2
30 50 70
40 80
60
如您所见,团队30,50和70拥有相同的成员,因此他们共享一行。同样,团队40和80拥有相同的成员,因此他们共享一行。只有60队(在本例中)才是唯一的。
在团队重复的情况下,我不关心哪个团队ID在哪个列中。此外,团队可能有两个以上的重复。团队规模从2名成员到8名成员。
答案 0 :(得分:3)
此答案提供您要求的输出数据格式。我将重复的团队留在一个变量中,因为我认为这是处理任意数量的重复项的更好方法。
require(dplyr)
df %>%
arrange(Team, Person) %>% # this line is necessary in case the rest of your data isn't sorted
group_by(Team) %>%
summarize(players = paste0(Person, collapse = ",")) %>%
group_by(players) %>%
summarize(teams = paste0(Team, collapse = ",")) %>%
mutate(
original_team = ifelse(grepl(",", teams), substr(teams, 1, gregexpr(",", teams)[[1]][1]-1), teams),
dup_teams = ifelse(grepl(",", teams), substr(teams, gregexpr(",", teams)[[1]][1]+1, nchar(teams)), NA)
)
结果:
Source: local data frame [3 x 4]
players teams original_team dup_teams
1 1,2,3,4 30,50,70 30 50,70
2 11,22 40,80 40 80
3 15,16,17 60 60 NA
答案 1 :(得分:2)
将此用作样本数据
dd<-structure(list(Person = c(1L, 2L, 3L, 4L, 11L, 22L, 1L, 2L, 3L,
4L, 15L, 16L, 17L, 1L, 2L, 3L, 4L, 11L, 22L), Team = c(30L, 30L,
30L, 30L, 40L, 40L, 50L, 50L, 50L, 50L, 60L, 60L, 60L, 70L, 70L,
70L, 70L, 80L, 80L)), .Names = c("Person", "Team"),
class = "data.frame", row.names = c(NA, -19L))
您可以尝试使用table()/ interaction()来查找重复的组。例如
tt <- with(dd, table(Team, Person))
grp <- do.call("interaction", c(data.frame(unclass(tt)), drop=TRUE))
split(rownames(tt), grp)
返回
$`1.1.1.1.0.0.0.0.0`
[1] "30" "50" "70"
$`0.0.0.0.0.1.1.1.0`
[1] "60"
$`0.0.0.0.1.0.0.0.1`
[1] "40" "80"
所以小组&#34;名字&#34;实际上只是每个人的会员指标。如果您愿意,可以使用setNames()
轻松地重命名它们。但是在这里它会使相应的团队崩溃。
答案 2 :(得分:2)
不完全是您想要的格式,但非常有用:
# using MrFlick's data
library(dplyr)
dd %>% group_by(Team) %>%
arrange(Person) %>%
summarize(team.char = paste(Person, collapse = "_")) %>%
group_by(team.char) %>%
arrange(team.char, Team) %>%
mutate(duplicate = 1:n())
Source: local data frame [6 x 3]
Groups: team.char
Team team.char duplicate
1 40 11_22 1
2 80 11_22 2
3 60 15_16_17 1
4 30 1_2_3_4 1
5 50 1_2_3_4 2
6 70 1_2_3_4 3
(如果数据尚未排序,则在arrange(Person)
行编辑,从@Reed的回答中得到了想法。)
答案 3 :(得分:2)
另外两个基本R选项(尽管不完全是所需的输出):
DF2 <- aggregate(Person ~ Team, DF, toString)
> split(DF2$Team, DF2$Person)
$`1, 2, 3, 4`
[1] 30 50 70
$`11, 22`
[1] 40 80
$`15, 16, 17`
[1] 60
或者
( DF2$DupeGroup <- as.integer(factor(DF2$Person)) )
Team Person DupeGroup
1 30 1, 2, 3, 4 1
2 40 11, 22 2
3 50 1, 2, 3, 4 1
4 60 15, 16, 17 3
5 70 1, 2, 3, 4 1
6 80 11, 22 2
请注意,问题中显示的预期输出要么在某些列条目中添加NAs或空字符串,因为在data.frame中,所有列必须具有相同的行数。对于列表而言,这是不同的,正如您在一些答案中所看到的那样。
第二个选项,但是使用data.table,因为aggregate
对于大数据来说往往很慢:
library(data.table)
setDT(DF)[, toString(Person), by=Team][,DupeGroup := .GRP, by=V1][]
Team V1 DupeGroup
1: 30 1, 2, 3, 4 1
2: 40 11, 22 2
3: 50 1, 2, 3, 4 1
4: 60 15, 16, 17 3
5: 70 1, 2, 3, 4 1
6: 80 11, 22 2
答案 4 :(得分:2)
使用uniquecombs
包中的mgcv
:
library(mgcv)
library(magrittr) # for the pipe %>%
# Using MrFlick's data
team_names <- sort(unique(dd$Team))
unique_teams <- with(dd, table(Team, Person)) %>% uniquecombs %>% attr("index")
printout <- unstack(data.frame(team_names, unique_teams))
> printout
$`1`
[1] 60
$`2`
[1] 40 80
$`3`
[1] 30 50 70
现在您可以使用类似this answer的内容以表格形式打印它(请注意,这些组是按列排列的,而不是像问题中那样按行排列):
attributes(printout) <- list(names = names(printout)
, row.names = 1:max(sapply(printout, length))
, class = "data.frame")
> printout
1 2 3
1 60 40 30
2 <NA> 80 50
3 <NA> <NA> 70
Warning message:
In format.data.frame(x, digits = digits, na.encode = FALSE) :
corrupt data frame: columns will be truncated or padded with NAs