Reputation: 113
I have a list of ids and places where these ids have been. Now I want to find pairs of ids that have most places in common.
My data frame looks like this:
id place
Dave Paris
Dave Moscow
Dave New York
Joe New York
Joe Tokyo
Stuart Paris
Stuart Moscow
Stuart New York
Stuart Tokyo
The results should look like this:
pair1 pair2 count
Dave Joe 1
Dave Stuart 3
Joe Stuart 2
I tried split to divide the data:
temp = split(df$name, df$place)
So I now have the places grouped, but I didn't get further.
The original dataset has about 100.000 unique ids.
Can anybody help me to find a good and fast solution? Thanks!
Upvotes: 2
Views: 451
Reputation: 7232
Or...
library(dplyr)
df1 %>%
left_join(df1, by = "place") %>%
filter(id.x < id.y) %>%
group_by(id.x, id.y) %>%
summarise(count = n())
EDIT:
If IDs are factors operator <
won't work. Conversion adds another line to the solution (credits to Steven Beaupré):
df1 %>%
left_join(df1, by = "place") %>%
mutate_each(funs(as.character(.))) %>%
filter(id.x < id.y) %>%
group_by(id.x, id.y) %>%
summarise(count = n())
Upvotes: 3
Reputation: 21641
For a dplyr
-esque solution,
You could do:
left_join(df, df, by = "place") %>%
rename(pair1 = id.x, pair2 = id.y) %>%
filter(!pair1 == pair2, !duplicated(t(apply(., 1, sort))) == TRUE) %>%
count(pair1, pair2)
Upvotes: 1
Reputation: 887881
You may try
library(reshape2)
tbl <- crossprod(table(df1[2:1]))
tbl[upper.tri(tbl, diag=TRUE)] <- 0
res <- subset(melt(tbl), value!=0)
colnames(res) <- c(paste0('pair',1:2), 'count')
row.names(res) <- NULL
res
# pair1 pair2 count
#1 Joe Dave 1
#2 Stuart Dave 3
#3 Stuart Joe 2
Or another option is
Subdf <- subset(merge(df1, df1, by.x='place',
by.y='place'), id.x!=id.y)
Subdf[-1] <- t(apply(Subdf[-1], 1, sort))
aggregate(place~., unique(Subdf), FUN=length)
# id.x id.y place
#1 Dave Joe 1
#2 Dave Stuart 3
#3 Joe Stuart 2
Upvotes: 3