2013-02-26 14 views
5

Chcę dokonać podziału danych, jeśli każda wartość w wierszu jest większa niż odpowiedni wiersz w innej ramce danych. Muszę też pominąć niektóre najlepsze wiersze. Te poprzednie pytania nie może mi pomóc, ale jest powiązany:Podział na podstawie wartości innej ramki danych w R

Subsetting a data frame based on contents of another data frame

Subset data using information from a different data frame [r]

> A 
    name1 name2 
cond trt ctrl 
hour  0  3 
A  1  1 
B  10  1 
C  1  1 
D  1  1 
E  10 10 
> B 
    name1 name2 
cond trt ctrl 
hour  0  3 
A  1  1 
B  1 10 
C  1  1 
D  1  1 
E  1  1 

chcę tego. Tylko wiersze, gdzie wszystkie wartości były większe niż A-B:

 name1 name2 
cond trt ctrl 
hour  0  3 
E  10 10 

Próbowałem te 3 linie:

subset(A, TRUE, select=(A[3:7,] > B[3:7,])) 
subset(A, A > B) 
A[A[3:7,] > B[3:7,]] 

Dzięki tak dużo. Oto kod, aby wygenerować dane:

A <- structure(list(name1 = c("trt", "0", "1", "10", "1", "1", "10" 
), name2 = c("ctrl", "3", "1", "1", "1", "1", "10")), .Names = c("name1", 
"name2"), row.names = c("cond", "hour", "A", "B", "C", "D", "E" 
), class = "data.frame") 
B <- structure(list(name1 = c("trt", "0", "1", "1", "1", "1", "1"), 
    name2 = c("ctrl", "3", "1", "10", "1", "1", "1")), .Names = c("name1", 
"name2"), row.names = c("cond", "hour", "A", "B", "C", "D", "E" 
), class = "data.frame") 
############# pytanie następcze poprosił 2/28/13

Error when subsetting based on adjusted values of different data frame in R

+1

wartości rzędu 'godzinach nie przekraczają. Czy chcesz zignorować ten wiersz? –

+0

Tak, chcę ignorować kategorie godzin i warunków – chimpsarehungry

Odpowiedz

5
N <- nrow(A) 
cond <- sapply(3:N, function(i) sum(A[i,] > B[i,])==2) 
rbind(A[1:2,], subset(A[3:N,], cond)) 
+0

To jest bardzo dobre. Widzę, że włączasz funkcję do zastosowania do tych wartości. Ale jestem zdezorientowany co do tego? Czy sapply używa pętli lub czegoś podobnego? Naprawdę podoba mi się to, że mogę teraz zmienić sumę == 2 na 1, jeśli chcę, aby 50% wartości w A było większe niż B. – chimpsarehungry

+0

Strona z uwagami: użycie sumy jest dobre, ale jest to trochę podstępne. Co jeśli masz warunek taki jak A.name1 **> ** A.name2 i A.name1 ** <** B.name2? – agstudy

+0

Bardzo prawdziwa agstudy. To jest właśnie miejsce, w którym planuję pójść z tym. Szybkość wydaje się być w porządku, redmode zabrał 20 sekund z moim prawdziwym zestawem danych. Ale masz rację co do problemu, gdy dodajesz więcej logiki. – chimpsarehungry

2

If i zmienić nazwę macierze amat i bmat, następnie

amat[which(sapply(1:nrows(amat),function(x) prod(amat[x,]>bmat[x,]))==1),] 
[1] 10 10 

i można wkleić wiersz „godzin” ponownie w razie potrzeby.

+0

Zasadniczo to samo co @redmode, więc Uważaj się za ninja w czasie, ale nie w zaciemnianiu. –

+1

Zgubiłeś mój alfabet Carl. – chimpsarehungry

3

Myślę, że lepiej jest używać SQL do takiego filtrowania między tabelami. Jest czysty i czytelny (zachowujesz logikę reguł).

library(sqldf) 
sqldf('SELECT DISTINCT A.* 
     FROM A,B 
     WHERE A.name1 > B.name1 
     AND A.name2 > B.name2') 
    name1 name2 
1 trt ctrl 
2 10 10 
+0

"Czyste i czytelne"? Jakim jesteś producentem oprogramowania?:-) –

+0

@CarlWitthoft przepraszam za mój angielski. Chodzi o to, że to rozwiązanie nie ukrywa warunków początkowych, takich jak używanie sumy lub prod w 2 innych rozwiązaniach. Myślę też, że jest to szybsze niż sapply (może wolniejsze niż rozwiązanie data.table, które ma tę samą logikę). W każdym razie, jestem programistą .net, jak próbować nauczyć się tych dni (nie jestem pewien, aby zrozumieć bardzo dobrze "oprogramowanie"). – agstudy

+2

Po prostu żartuje, mówiąc, że twoje rozwiązanie jest zbyt czytelne dla człowieka. Podoba mi się to. Będę musiał zdobyć tę bibliotekę. – chimpsarehungry

3

warunkiem data.table rozwiązanie:

library(data.table) 

# just to preserve the order, non-alphabetically 
idsA <- factor(rownames(A), levels=rownames(A)) 
idsB <- factor(rownames(B), levels=rownames(B)) 

# convert to data.table with id 
ADT <- data.table(id=idsA, A, key="id") 
BDT <- data.table(id=idsB, B, key="id") 

# filter as needed 
ADT[BDT][name1 > name1.1 & name2 > name2.1, list(id, name1, name2)] 
+0

Uwielbiam, gdy mam takie różnorodne rozwiązania. Dzięki Ricardo – chimpsarehungry

+0

Czy istnieje sposób, aby ta część filtrująca nie polegała na nazwach kolumn. Po prostu filtruj w oparciu o odpowiednią lokalizację kolumn w A i B. – chimpsarehungry

+0

Tak, możesz zrobić filtr tak jak w przypadku danych.frame, ale na końcu dodaj ', z = FALSE] –

Powiązane problemy