2013-02-26 15 views
5

Desidero sottoporre a set di dati se ogni valore nella riga è maggiore della rispettiva riga in un diverso frame di dati. Devo anche saltare alcune righe in alto. Queste domande precedenti non mi ha aiutato, ma è correlato:Subsetting basato su valori di un diverso frame di dati in 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 

voglio questo. Solo le righe in cui Tutti i valori erano maggiori in A a B:

 name1 name2 
cond trt ctrl 
hour  0  3 
E  10 10 

ho provato queste 3 linee:

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

Grazie mille. Ecco il codice per generare i dati:

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") 
############# domanda di follow-up ha chiesto 2/28/13

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

+1

valori di riga i "ore non superano. Vuoi ignorare quella riga? –

+0

Sì, voglio ignorare l'ora e le categorie cond. – chimpsarehungry

risposta

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

Questo è molto buono. Vedo che stai includendo una funzione da applicare a quei valori. Ma io sono confuso riguardo l'io? Utilizza tranquillamente un ciclo o qualcosa del genere? Quello che mi piace davvero di questo è che ora posso cambiare sum == 2 a 1 se voglio che il 50% dei valori in A sia maggiore di B. – chimpsarehungry

+0

Nota: l'uso della somma è buono, ma è un po 'di trucco. Cosa succede se hai una condizione come A.name1 **> ** A.name2 e A.name1 ** <** B.name2? – agstudy

+0

Agstudy molto vero. Questo è in realtà dove ho intenzione di andare con questo. La velocità sembra a posto, la modalità rossa ha impiegato 20 secondi con il mio vero set di dati. Ma hai ragione riguardo ad un problema quando aggiungi più logica. – chimpsarehungry

2

Se ho rinominare i matrici amat e bmat, quindi

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

e si può incollare la riga 'ore' indietro se lo si desidera.

+0

Che è praticamente la stessa cosa che ha @redmode, quindi I mi considero ninja in tempo ma non in offuscamento. –

+1

Hai perso il mio alfabeto Carl. – chimpsarehungry

3

Penso che sia meglio usare SQL per tale filtraggio tra tabelle. È pulito e leggibile (si mantiene la logica delle regole).

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

"Pulito e leggibile"? Che tipo di software jock sei comunque?:-) –

+0

@CarlWitthoft scusa per il mio inglese. Intendo per pulito che questa soluzione non nasconda la condizione di origine come l'utilizzo di sum o prod nelle altre 2 soluzioni. Penso anche che sia più veloce di quanto sappia (forse più lento della soluzione data.table che ha la stessa logica). Ad ogni modo, sono un programmatore .net come cercare di imparare i giorni di R (non sono sicuro di capire molto bene il "software jock"). – agstudy

+2

Sta scherzando, dicendo che la soluzione è troppo leggibile. Mi piace comunque. Dovrò prendere quella libreria. – chimpsarehungry

3

requisito soluzione data.table:

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

Amo quando ottengo una tale varietà di soluzioni. Grazie Ricardo – chimpsarehungry

+0

C'è un modo per fare in modo che la parte filtrante non faccia affidamento sui nomi delle colonne. Basta filtrare in base alla rispettiva posizione delle colonne in A e B. – chimpsarehungry

+0

Sì, puoi filtrare come faresti con un data.frame, ma alla fine, aggiungi ', with = FALSE]' –

Problemi correlati