2016-06-09 16 views
6

Questa è una domanda successiva della domanda che ho chiesto a here. Lì ho imparato a) come farlo per le colonne (vedi sotto) eb) che la selezione di righe e colonne sembra essere gestita in modo abbastanza diverso in R, il che significa che non posso usare lo stesso approccio per le righe.Come suddividere un dataframe selezionando un intervallo di colonne e righe in base ai nomi e non agli indici?

Quindi supponiamo che ho un dataframe panda come questo:

import pandas as pd 
import numpy as np 

df = pd.DataFrame(np.random.randint(10, size=(6, 6)), 
        columns=['c' + str(i) for i in range(6)], 
        index=["r" + str(i) for i in range(6)]) 

    c0 c1 c2 c3 c4 c5 
r0 4 2 3 9 9 0 
r1 9 0 8 1 7 5 
r2 2 6 7 5 4 7 
r3 6 9 9 1 3 4 
r4 1 1 1 3 0 3 
r5 0 8 5 8 2 9 

poi mi può facilmente selezionare righe e colonne con i loro nomi in questo modo:

print df.loc['r3':'r5', 'c1':'c4'] 

che restituisce

c1 c2 c3 c4 
r3 9 9 1 3 
r4 1 1 3 0 
r5 8 5 8 2 

Come dovrei farlo in R? Dato un dataframe come questo

df <- data.frame(c1=1:6, c2=2:7, c3=3:8, c4=4:9, c5=5:10, c6=6:11) 
rownames(df) <- c('r1', 'r2', 'r3', 'r4', 'r5', 'r6') 

    c1 c2 c3 c4 c5 c6 
r1 1 2 3 4 5 6 
r2 2 3 4 5 6 7 
r3 3 4 5 6 7 8 
r4 4 5 6 7 8 9 
r5 5 6 7 8 9 10 
r6 6 7 8 9 10 11 

A quanto pare, se so che gli indici delle mie righe desiderate/colonne, posso semplicemente fare:

df[3:5, 1:4] 

ma potrei eliminare righe/colonne in tutta la mia analisi in modo che Preferirei selezionare per nome piuttosto che per indice. Dal link qui sopra ho imparato che per le colonne il seguente dovrebbe funzionare:

subset(df, select=c1:c4) 

che restituisce

c1 c2 c3 c4 
r1 1 2 3 4 
r2 2 3 4 5 
r3 3 4 5 6 
r4 4 5 6 7 
r5 5 6 7 8 
r6 6 7 8 9 

Ma come potevo anche selezionare un intervallo di righe in base al nome, allo stesso tempo?

In questo caso particolare, potrei ovviamente utilizzare grep ma per quanto riguarda le colonne con nomi arbitrari?

E io non voglio usare

df[c('r3', 'r4' 'r5'), c('c1','c2', 'c3', 'c4')] 

ma una fetta vera e propria.

risposta

6

È possibile utilizzare which() con rownames:

subset(df[which(rownames(df)=='r3'):which(rownames(df)=='r5'),], select=c1:c4) 


    c1 c2 c3 c4 
r3 3 4 5 6 
r4 4 5 6 7 
r5 5 6 7 8 
+0

Sì, dovrei sii più preciso (modificherai la mia domanda): Dovrebbe essere w ork per nomi arbitrari; quelli qui sarebbero davvero facili da analizzare :) – Cleb

+0

ok ho letto troppo presto all'inizio. è di questo che hai bisogno? – HubertL

+0

Ottimo! Sì, funziona bene.Lo investo per ora e lo accetto più tardi in base alla qualità di altre risposte. – Cleb

2

Usa match per trovare la posizione di nomi riga specifica.

df[match("r3", rownames(df)):match("r5", rownames(df)), match("c1", colnames(df)):match("c4", colnames(df))] 

    c1 c2 c3 c4 
r3 3 4 5 6 
r4 4 5 6 7 
r5 5 6 7 8 
+0

Ma poi ho bisogno di specificare le righe e le colonne che effettivamente voglio evitare (ho modificato la mia domanda per renderla più chiara); immagina questo per 100 righe/colonne che vuoi selezionare ... – Cleb

+0

Per favore controlla le mie modifiche. Funzionerebbe per te? – milan

+0

Sì, anche questo funziona (ingrandito)! Hai solo bisogno di correggere gli errori di battitura in 'index.c'. – Cleb

3

È possibile scrivere una funzione che un pò si darà lo stesso comportamento

'%:%' <- function(object, range) { 
    FUN <- if (!is.null(dim(object))) { 
    if (is.matrix(object)) colnames else names 
    } else identity 
    wh <- if (is.numeric(range)) range else which(FUN(object) %in% range) 
    FUN(object)[seq(wh[1], wh[2])] 
} 

df <- data.frame(c1=1:6, c2=2:7, c3=3:8, c4=4:9, c5=5:10, c6=6:11) 
rownames(df) <- c('r1', 'r2', 'r3', 'r4', 'r5', 'r6') 

utilizzarlo come

df %:% c('c2', 'c4') 
# [1] "c2" "c3" "c4" 

rownames(df) %:% c('r2', 'r4') 
# [1] "r2" "r3" "r4" 

per la tua domanda

df[rownames(df) %:% c('r3', 'r5'), df %:% c('c1', 'c5')] 
# c1 c2 c3 c4 c5 
# r3 3 4 5 6 7 
# r4 4 5 6 7 8 
# r5 5 6 7 8 9 
Problemi correlati