Pytanie Jaka jest różnica między listą a parą w R?


Czytając dokumentację dla list, znalazłem odniesienia do par, ale nie było dla mnie jasne, w jaki sposób różniły się od list.


18
2018-04-02 15:47


pochodzenie




Odpowiedzi:


Pary w dzień po dniu R

Istnieją dwa miejsca, w których listy par pojawiają się powszechnie w codziennym R. Jednym z nich jest funkcja formals:

str(formals(var))

Drugi to obiekty językowe. Na przykład:

quote(1 + 1)

tworzy parę języków typów (LANGSXP wewnętrznie). Głównym powodem, dla którego warto zwrócić uwagę na to, jest to, że operacje takie jak length(<language object>) lub language_object[[x]] może być powolny ze względu na sposób, w jaki pary są przechowywane wewnętrznie (chociaż obiekty języków długich parlist są dość rzadkie, wyrazy nie są parami).

Zwróć uwagę, że puste elementy są tylko symbolami o zerowej długości i możesz je zapisać na liście, jeśli oszukasz trochę (chociaż prawdopodobnie nie powinieneś tego robić):

list(x=substitute(x, alist(x=)))  # hack alert

Wszystko to powiedziawszy, w większości przypadków, OP jest poprawne, że nie musisz martwić się o pary za dużo, chyba że piszesz kod C do użytku w R.

Wewnętrzne różnice między listami i parami

Pary i lista różnią się głównie w ich strukturze przechowywania. Pary są przechowywane jako łańcuch węzłów, gdzie każdy węzeł wskazuje na lokalizację następnego węzła oprócz zawartości węzła i "nazwy" węzła (patrz Artykuł wiki CAR / CDR do ogólnej dyskusji). Między innymi oznacza to, że nie możesz wiedzieć, ile elementów znajduje się na liście pary, chyba że wiesz, który element jest pierwszy, a następnie przechodzisz przez całą listę.

Pary są często używane w obiektach R i istnieją w normalnym użyciu R, ale w większości przypadków są zamaskowane przez metody drukowania lub dostępu i / lub wymuszane na listach w przypadku dostępu.

Listy są także listą adresów, ale w przeciwieństwie do par, wszystkie adresy są przechowywane w jednej ciągłej lokalizacji pamięci, a całkowita długość jest śledzona. Ułatwia to dostęp do dowolnych elementów listy według lokalizacji, ponieważ można po prostu wyszukać adres w tabeli pamięci. W przypadku pary musisz przejść od węzła do węzła, aż w końcu dotrzesz do pożądanego węzła. Nazwy są również przechowywane jako atrybuty odpowiedniej listy, zamiast być dołączane do każdego węzła pary.

Zalety list

Jedną (na ogół małą) zaletą parlist jest to, że można do nich dodać przy minimalnym obciążeniu, ponieważ wystarczy zmodyfikować najwyżej dwa węzły (węzeł przed nowym węzłem i sam nowy węzeł), natomiast z listą może być potrzebna aby ponownie przydzielić całą tablicę adresów ze wzrostem wielkości (zazwyczaj nie stanowi to problemu, ponieważ tablica adresów jest zwykle bardzo mała w porównaniu do rozmiaru danych, do których wskazuje tabela). Istnieje również wiele algorytmów, które specjalizują się w manipulowaniu parami (na przykład sortowaniu, indeksowaniu itp.), Ale można je również przenieść do normalnych list.

Mniej istotne dla codziennego użytku, ponieważ możesz to zrobić tylko w wewnętrznych, bardzo łatwo zmienić listę z perspektywy programowania, zmieniając to, co dowolny dowolny element wskazuje.

Luźno powiązane z powyższym, pary są prawdopodobnie bardziej wydajne, gdy masz wysoce zagnieżdżone obiekty. listy mogą z łatwością replikować tę strukturę, ale każda lista i lista zagnieżdżona będzie obarczona dodatkową tabelą adresów pamięci. Jest to prawdopodobnie powód, dla którego pary są używane dla obiektów językowych, które najprawdopodobniej mają wysoki współczynnik zagnieżdżenia / elementu.

Aby uzyskać więcej informacji, zobacz R Internals (wyszukaj odpowiednio LISTSXP i VECSXP, pary i listy w połączonej lokalizacji).

edytować: co ciekawe, eksperyment do porównywania śladu pamięci listy z listą par pokazuje, że paralista jest większa, więc argument efektywności przechowywania może być nieprawidłowy (nie wiem, czy object.size można tu zaufać):

> plist_to_list <- function(x) {
+   if(is.call(x)) x <- as.list(x)
+   if(length(x) > 1) for(i in 2:length(x)) x[[i]] <- Recall(x[[i]])
+   x
+ }
> add_quote <- function(x, y) call("+", x, y)
> x <- Reduce(add_quote, lapply(letters, as.name))
> object.size(x)
7056 bytes
> y <- plist_to_list(x)
> object.size(y)
4656 bytes

11
2018-04-02 17:35





Po pierwsze, pary są przestarzałe

pary są przestarzałe do normalnego użytku. Nigdy nie będziesz musiał się nimi przejmować, chyba że pracujesz nad wewnętrznymi R.


listy może zawierać nazwane elementy

Każdy element na liście w R może mieć nazwę. Możesz uzyskać dostęp do każdego elementu na liście według nazwy lub indeksu liczbowego.

Oto przykład listy, w której drugi element ma nazwę "drugi":

> my.list <- list('A',second='B','C')
> my.list
[[1]]
[1] "A"

$second
[1] "B"

[[3]]
[1] "C"

Wszystkie elementy mogą być indeksowane według ich pozycji na liście. Do nazwanych elementów można dodatkowo uzyskać dostęp poprzez nazwę:

> my.list[[2]]
[1] "B"
> my.list$second
[1] "B"

Ponadto każdy element na liście jest wektorem, nawet jeśli jest to tylko wektor zawierający pojedynczy element. Aby uzyskać więcej informacji o listach, zobacz Jak poprawnie używać list w R?.


pary może zawierać pusty nazwane elementy

Paralista jest w zasadzie taka sama jak lista, z tym wyjątkiem, że para może zawierać pusty element o nazwie, ale lista nie może. Ponadto, parą jest skonstruowana przy użyciu alist funkcjonować.

> list('A',second=,'C')
Error in as.pairlist(list(...)) : argument is missing, with no default
> alist('A',second=,'C')
[[1]]
[1] "A"

$second


[[3]]
[1] "C"

Ale, jak wspomniano wcześniej, są one przestarzałe. Nie mają żadnej korzyści ani przewagi nad listami, które znam.


13
2018-04-02 15:47



Oto coś ciekawego: chociaż standardowa lista nie może zawierać pustego elementu, może pomieścić bquote() jako element. Do pisania funkcji dla tablic o nieokreślonej liczbie wymiarów, używając do.call("[", c(list(arr), ...)) jest bardzo pomocny, gdzie możesz chcieć dołączyć listę argumentów bquote(). Przypuszczam bquote() zasadniczo pozwala list zrobić wszystko alist mogą. Masz pojęcie, dlaczego para jest nazywana parą? - Bazz