2017-09-05 15 views
7

Mam problem z podzbiorem danych.frame na podstawie wzajemności wartości w wierszu i kolumnie.Podzbiór według wzajemności w wierszach i kolumnach

Oto przykład df do zilustrowania problemu:

rater <- c(21, 23, 26, 24) 
ratee <- c(24, 21, 23, 21) 
rating.data <- data.frame(rater, ratee) 

wyjściowa:

rater ratee 
1 21 24 
2 23 21 
3 26 23 
4 24 21 

Chciałbym podzbiór ten df tylko o utrzymanie wiersze, które mają wartości wzajemnych.

Powstały podzbiór powinna wyglądać następująco:

rater ratee 
1 21 24 
4 24 21 

Wszelkie myśli będą mile widziane!

+0

Używasz niewłaściwie słowa "wzajemność". 1/x jest odwrotnością x. –

+0

czy chcesz skończyć z macierzą symetryczną ??? –

+0

https://stackoverflow.com/questions/28574006/unique-rows-considering-two-columns-in-r-without-order również sprawdź link – Wen

Odpowiedz

6

Inna możliwość:

library(dplyr) 
rating.data %>% inner_join(.,.,by=c("rater" = "ratee","ratee"="rater")) 

Albo to, z jakiegoś powodu, to jest dwa razy szybciej na małej przykład (choć wolniej niż rozwiązania akrun za) :

merge(rating.data,setNames(rating.data,rev(names(rating.data)))) 

utrzymanie drugiego rozwiązania elastycznego dowcipu h twoje dodatkowe kolumny:

merge(rating.data,setNames(rating.data[,c("rater","ratee")],c("ratee","rater"))) 
+0

Dzięki!To jest właśnie to, czego szukałem, ponieważ nie chciałem stracić reszty df. To pozwala mi określić kolumny, które mam na myśli. Dziękuję za przeczytanie mojego umysłu! – SeekingData

+0

Nie ma za co, rozwiązanie akruna może zostać łatwo zaadaptowane, jeśli po prostu umieścisz 'rating.data [, c (" rater "," ratee ")]' w pierwszej linii, może to być również szybsze, jeśli jest to problem . –

8

Możemy sortować według wiersza, a następnie użyć duplicated

m1 <- t(apply(rating.data, 1, sort)) 
rating.data[duplicated(m1)|duplicated(m1, fromLast = TRUE),] 
# rater ratee 
#1 21 24 
#4 24 21 
+1

To jest świetne! Próbowałem myśleć o tym, jak użyć duplikatu w celu rozwiązania problemu. To działa dobrze! Dziękuję Ci! – SeekingData

+1

@SeekingData, jeśli ta odpowiedź ci pomoże, możesz ją zaakceptować :) – Wen

+0

Chciałabym móc przyjąć obie. Dziękuję, Akrun! – SeekingData

2
library(data.table) 
N=10#number of rows 
dt1<-data.table(a=1:N,b=sample(N))#create the data.table that holds the info 

dt1[,d:=ifelse(a<b,paste0(a,"_",b),paste0(b,"_",a))]#create unique key per pair respecting the rule "min_max" 
setkey(dt1,d)#setting the key 
dt1[dt1[,.N,d][N!=1],.(a,b)] #keep only the pairs that appear more than once 
1

w duchu podobnym do akrun na sposób, rbind data.frame do kopii z kolumn odwróconych. znajdź duplikaty, zaczynając od dołu, które następnie zwrócą TRUE dla wierszy oryginalnego data.frame. Podziel ten wektor logiczny za pomocą [seq_len(nrow(rating.data))], aby zwrócić wektor o odpowiedniej długości do [, aby uzyskać podzbiór w wierszach.

rating.data[duplicated(rbind(rating.data, 
          unname(unclass(rating.data[2:1]))), 
         fromLast=TRUE)[seq_len(nrow(rating.data))],] 
    rater ratee 
1 21 24 
4 24 21 
2

Można również użyć pmin i pmax pomóc z grupy, a następnie filtrować wszystkich grupach mających więcej niż jeden wpis, tzn

library(dplyr) 

df %>% 
group_by(grp = paste0(pmin(rater, ratee), pmax(rater, ratee))) %>% 
filter(n() > 1) %>% 
ungroup() %>% 
select(-grp) 

co daje,

# A tibble: 2 x 2 
    rater ratee 
    <dbl> <dbl> 
1 21 24 
2 24 21 
+1

Myślałem o podejściu 'pmin/pmax'. Byłoby szybciej – akrun

Powiązane problemy