Menu

Liste in R: creare, accedere ([[ vs $ vs [) e modificare

Le liste sono il contenitore di R dove va bene tutto: tipi misti, strutture annidate, interi data frame. L'abilità chiave è sapere quando [ restituisce una lista più piccola e quando [[ restituisce l'elemento stesso.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Una lista contiene qualsiasi cosa

Un vettore ha una regola ferrea: ogni elemento deve essere dello stesso tipo. Una lista non ha questa regola. Ogni elemento di una lista può essere di un tipo diverso, di una lunghezza diversa, perfino un'altra lista. È il contenitore generico di R:

length() riporta 4, quattro elementi, anche se uno di loro (scores) contiene a sua volta tre numeri. Una lista conta i suoi scomparti, non quello che c'è dentro. str() (struttura) è il modo più rapido per vedere cosa contiene davvero una lista: una riga per elemento con nome, tipo e un'anteprima. Fai di str() un riflesso: ogni volta che una funzione ti restituisce qualcosa e non sei sicuro di cosa sia, passalo a str().

I nomi sono facoltativi (list(1, "a", TRUE) è valido) ma quasi sempre vale la pena averli: una lista con nomi si documenta da sola.

I tre modi per entrare: [, [[ e $

È la parte delle liste che tutti sbagliano almeno una volta, quindi vediamola per bene. Ci sono tre operatori di accesso, e fanno due lavori diversi:

  • [ restituisce una lista più piccola: un contenitore dello stesso tipo, con dentro quello che hai selezionato.
  • [[ restituisce l'elemento stesso: il valore vero e proprio dentro lo scomparto.
  • $ è una scorciatoia per [[ con un nome letterale: person$age è person[["age"]].

La differenza è invisibile quando stampi alla buona e molto visibile nel momento in cui provi a fare un calcolo:

person["scores"] ha classe "list": una lista di lunghezza 1 con dentro il vettore dei punteggi. person[["scores"]] ha classe "numeric": il vettore stesso, pronto per mean(). Chiama mean() sulla versione con parentesi singole e ottieni un errore che dice che l'argomento non è numerico; quel messaggio di errore è quasi sempre il segno che hai usato [ dove intendevi [[.

Una metafora che resta in testa: una lista è un treno. [ ti dà un treno più corto, ma sempre un treno. [[ apre un vagone e ti consegna il carico.

Quindi quando [ è lo strumento giusto? Quando vuoi più elementi e vuoi tenerli impacchettati:

Non puoi estrarre due elementi "in sé" in una volta sola, perché due valori hanno bisogno di un contenitore, quindi la selezione di più elementi usa sempre le parentesi singole e restituisce sempre una lista.

Un'altra differenza: $ usa la corrispondenza parziale (person$sc trova scores se non è ambiguo), comoda in console e rischiosa negli script. Nel codice che deve continuare a funzionare, preferisci [[ con il nome completo: accetta anche un nome salvato in una variabile, cosa che $ non sa fare.

Aggiungere, modificare, rimuovere

Le liste crescono e si accorciano con una semplice assegnazione, senza bisogno di metodi speciali per aggiungere:

  • Assegnare a un nome che non esiste ancora aggiunge l'elemento.
  • Assegnare a un nome esistente lo sostituisce.
  • Assegnare alla posizione length(x) + 1 aggiunge in fondo un elemento senza nome.
  • Assegnare NULL rimuove del tutto l'elemento: la lista si accorcia. (È l'unico caso in cui NULL funziona come comando di cancellazione; se hai davvero bisogno di salvare "niente" in uno scomparto, usa x["k"] <- list(NULL).)

Per unire due liste una dopo l'altra, c() funziona sulle liste proprio come sui vettori: c(list_a, list_b) restituisce un'unica lista più lunga.

Liste annidate

Dato che un elemento di una lista può essere un'altra lista, le liste si annidano a qualsiasi profondità, ed è per questo che sono la forma naturale di R per dati strutturati come JSON analizzato o risultati raggruppati:

Scendere in profondità significa solo concatenare gli operatori di accesso: ogni $ o [[ scende di un livello. Quando una struttura annidata diventa confusa, str(company) mostra l'intero albero in una volta, e str(company, max.level = 1) mostra solo il livello più alto.

Appiattire con unlist()

unlist() riduce una lista, per quanto profondamente annidata, a un singolo vettore:

Due cose da notare. Primo, unlist() costruisce i nomi al posto tuo (math1, math2, art) così puoi ancora capire da dove viene ogni valore. Secondo, ed è questa la trappola, un vettore contiene un solo tipo, quindi appiattire una lista mista converte tutto al tipo più flessibile presente. Il numero 1 è tornato come stringa "1". Se appiattisci e i tuoi numeri diventano testo, la lista non era uniforme come pensavi.

Perché le liste contano

Le liste possono sembrare un argomento da principianti che ti lascerai alle spalle. È il contrario: reggono l'intero linguaggio.

  • Le funzioni che restituiscono più cose restituiscono una lista. Le funzioni R restituiscono un solo oggetto; una lista permette a quell'unico oggetto di portare un valore stimato qui, una tabella di coefficienti là. Quando esegui una regressione, l'oggetto modello che ottieni è una lista (grande e con una classe): str() applicato a quell'oggetto lo dimostra.
  • Un data frame è una lista di colonne: vettori della stessa lunghezza con qualche comportamento in più. Tutto quello che hai appena imparato ($, [[, assegnare NULL per eliminare un elemento) vale alla lettera per le colonne dei data frame.
  • La famiglia apply, cioè lapply() e compagnia, prende una lista, applica una funzione a ogni elemento e restituisce una lista. Liste in entrata, liste in uscita: è la forma standard del calcolo ripetuto in R.

Cosa ti porti a casa

  • Le liste contengono qualsiasi cosa: tipi misti, lunghezze diverse, altre liste, interi data frame.
  • [ restituisce una lista più piccola; [[ restituisce l'elemento stesso; $ è [[ con un nome letterale. Devi fare calcoli? Ti serve [[ o $.
  • Aggiungi assegnando a un nome nuovo, rimuovi assegnando NULL, combina con c().
  • unlist() appiattisce in un vettore e intanto converte i tipi misti: controlla la classe del risultato.
  • I data frame sono liste di colonne, quindi queste conoscenze si trasferiscono direttamente.

Prossimo passo: le matrici, la controparte della lista con un solo tipo, righe e colonne.

Domande frequenti

Qual è la differenza tra [ e [[ in R?

Le parentesi quadre singole [ restituiscono sempre una lista che contiene gli elementi selezionati, cioè un contenitore più piccolo dello stesso tipo. Le parentesi doppie [[ entrano dentro e restituiscono l'elemento stesso. Se x$scores contiene un vettore numerico, x["scores"] è una lista di lunghezza 1 e x[["scores"]] è il vettore numerico. Usa [[ (o $) quando vuoi lavorare davvero con il valore.

Come si aggiunge un elemento a una lista in R?

Assegna a un nome che non esiste ancora: x$email <- "rosa@example.com" oppure x[["email"]] <- .... La lista cresce automaticamente. Per aggiungere in fondo senza un nome, assegna alla posizione successiva: x[[length(x) + 1]] <- value. Per rimuovere un elemento, assegnagli NULL: x$email <- NULL.

Come si converte una lista in un vettore in R?

unlist(x) appiattisce una lista (comprese quelle annidate) in un singolo vettore. Dato che un vettore contiene un solo tipo, tutto viene convertito al tipo più flessibile presente: una lista di numeri e stringhe diventa un vettore tutto di caratteri. Controlla il class() del risultato dopo averlo appiattito.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA