计算和识别R中的独特关系

时间:2016-06-01 18:26:12

标签: r count

我有一个包含2列的数据框:

Name       AvgSalary 
Alice      10000 
Bob        10000 
Charlie    10000 
Doug       10000 

现在我可以计算id1和id2的组合等于组合id2和id1的所有情况并返回它们,如下所示:

id1 <- c(123,456,789,122,345,678,901,126,567,890,001,002,130,122)
id2 <- c(121,122,123,456,125,126,127,678,129,130,131,132,890,987)
df <- cbind(id1,id2)
df
  id1 id2
 [1,] 123 121
 [2,] 456 122
 [3,] 789 123
 [4,] 122 456
 [5,] 345 125
 [6,] 678 126
 [7,] 901 127
 [8,] 126 678
 [9,] 567 129
[10,] 890 130
[11,]   1 131
[12,]   2 132
[13,] 130 890
[14,] 122 987

但是现在,我想要一个新的计数,其中id1只与id2相关,而id2只与id1相关,例如对于df,count将等于4,因为:

forwards<-paste(V1,V2)
backwards<-paste(V2,V1)

#identifying combinations

intersect(forwards, backwards)
[1] "456 122" "122 456" "678 126" "126 678" "890 130" "130 890"

#count combinations
length(intersect(forwards, backwards))
[1] 6

因此,新计数应排除这两种情况并计算如下情况:

id1==122 is related with id2==456 AND id1==456 is related with id2==122,
but id1 ==122 is too related with id2==987, 

我该怎么做?

2 个答案:

答案 0 :(得分:2)

以下是我使用data.table解决您问题的方法。也许有人可以帮助我们找到更直接的解决方案。

library(data.table)
df <- data.table(id1,id2) # get vectors as a data.table

# create forwards and backwards  columns
  df[ , forwards := paste(id1,id2)]
  df[ , backwards := paste(id2,id1)]

# count number of intersections between forwards and backwards  
  df [ forwards %in% backwards, .(count=.N)]

>    count
> 1:     6

现在这就是你所要求的,棘手的部分。

# add new column with number of pairs of id1
  df[ , pairs :=.N, by= id1]

# get all values that have more than one pair
  too_many_pairs <-  as.matrix(df[ pairs >1, .(id1,id2) ])

# solution
  df[  id1 %in% id2 & id2 %in% id1 & !(id1 %in% too_many_pairs) ]

>    id1 id2 
> 1: 678 126 
> 2: 126 678 
> 3: 890 130 
> 4: 130 890 

解释解决方案:

解决方案id1 %in% id2 & id2 %in% id1第一部分表示只保留id2的值,这些值也可以在id2中找到,反之亦然

解决方案!(id1 %in% too_many_pairs)第二部分表示删除具有多个对的id1的所有值

答案 1 :(得分:0)

这是一个Hadleyverse方法:

library(dplyr)
library(tidyr)

# make df a data.frame instead of a matrix
data.frame(df) %>% 
    # add row index
    add_rownames() %>% 
    # melt to long form
    gather(id, val, -rowname) %>% 
    # filter down to values repeated an even number of times
    group_by(val) %>% filter(n() %% 2 == 0) %>% 
    # filter down to rows with two values
    group_by(rowname) %>% filter(n() == 2) %>% 
    # spread back to wide form
    spread(id, val)

# Source: local data frame [4 x 3]
# Groups: rowname [4]
# 
#   rowname   id1   id2
#     (chr) (dbl) (dbl)
# 1      10   890   130
# 2      13   130   890
# 3       6   678   126
# 4       8   126   678