2009-11-16 17 views
31

Piszę kod R, aby utworzyć kwadratową macierz. Tak więc moje podejście jest:Najlepszy sposób na przydzielenie macierzy w R, NULL vs NA?

  1. Przeznaczyć matrycę o odpowiednim rozmiarze
  2. pętli każdego elementu mojej matrycy i wypełnić go z odpowiednią wartością

moje pytanie jest bardzo prosta: to, co jest najlepszy sposób na wstępną alokację tej macierzy? Zatem pory, dwa sposoby:

> x <- matrix(data=NA,nrow=3,ncol=3) 
> x 
    [,1] [,2] [,3] 
[1,] NA NA NA 
[2,] NA NA NA 
[3,] NA NA NA 

lub

> x <- list() 
> length(x) <- 3^2 
> dim(x) <- c(3,3) 
> x 
    [,1] [,2] [,3] 
[1,] NULL NULL NULL 
[2,] NULL NULL NULL 
[3,] NULL NULL NULL 

ile można zobaczyć, pierwsza jest bardziej zwięzły sposób, niż to drugie. Również ten pierwszy wypełnia macierz z NA, podczas gdy ta ostatnia jest wypełniona wartościami NULL.

Jaki jest "lepszy" sposób na zrobienie tego? W tym przypadku definiuję "lepsze" jako "lepszą wydajność", ponieważ jest to obliczenia statystyczne i ta operacja będzie miała miejsce z dużymi zbiorami danych.

Podczas gdy pierwsza z nich jest bardziej zwięzła, nie jest zapierająca dech w piersiach, łatwiejsza do zrozumienia, więc czuję, że to może pójść w jedną stronę.

Jaka jest różnica między NA i NULL w R? ? NA i? NULL powiedz mi, że "NA" ma długość "1", natomiast NULL ma długość "0" - ale czy jest tu więcej? Lub najlepsza praktyka? Wpłynie to na metodę, której używam do tworzenia mojej macierzy.

+1

Nie pytam, dlaczego chcesz * zapętlić * nad elementami macierzy? Czy możliwe jest użycie zamiast tego operacji wektoryzacji? To powinno być twoje następne pytanie tutaj! :) – Harlan

+0

@Harlan, co jest zasadniczo tym, co dostaję w tym pytaniu tutaj: http://stackoverflow.com/questions/1719447/outer-equivalent-for-non-vector-lists-in-r. Jeśli masz sugestię, chciałbym to usłyszeć! – poundifdef

Odpowiedz

44

Jeśli masz wątpliwości, sprawdź się. Pierwsze podejście jest łatwiejsze i szybsze.

> create.matrix <- function(size) { 
+ x <- matrix() 
+ length(x) <- size^2 
+ dim(x) <- c(size,size) 
+ x 
+ } 
> 
> system.time(x <- matrix(data=NA,nrow=10000,ncol=10000)) 
    user system elapsed 
    4.59 0.23 4.84 
> system.time(y <- create.matrix(size=10000)) 
    user system elapsed 
    0.59 0.97 15.81 
> identical(x,y) 
[1] TRUE 

Jeśli chodzi o różnicę pomiędzy NA a NULL:

Istnieje rzeczywiście cztery specjalne stałymi.

Ponadto istnieją cztery specjalne stałe, NULL, NA, Inf i NaN.

NULL służy do wskazania pustego obiektu. NA jest używane dla wartości danych nieobecnych ("niedostępne"). Inf oznacza nieskończoność, a NaN nie jest liczbą w rachunku zmiennoprzecinkowym IEEE (wyniki operacji odpowiednio 1/0 i 0/0, na przykład).

Możesz przeczytać więcej w the R manual on language definition.

+0

huh, również nie wiedział o system.time. Dziękuję bardzo! – poundifdef

+0

Jeśli zamierzasz porównywać metody, nie powinieneś zawijać obu metod w funkcji? Dodany jest dodatkowy nagłówek wywołania funkcji. – Dason

+0

@Dason W praktyce, jeśli ktoś miałby często używać dłuższej metody, czy nie byłby prawdopodobnie zawinięty w funkcję? Natomiast "matryca" pozostanie taka, jaka jest. – Gregor

3

Zgodnie z this article możemy zrobić więcej niż przedalokować z NA przez wcześniejsze przydzielenie z NA_real_. Z artykułu:

natychmiast po przypisaniu wartości numerycznej do dowolnej komórki w "x", macierz najpierw musi zostać przekształcona na wartość numeryczną po przypisaniu nowej wartości. Pierwotnie przydzielona macierz logiczna została przydzielona na próżno i po prostu dodaje niepotrzebny ślad pamięci i dodatkową pracę dla garbage collectora. Zamiast tego przydzielić za pomocą NA_real_ (lub NA_integer_ dla liczb całkowitych)

Zgodnie z zaleceniami: przetestujmy to.

testfloat = function(mat){ 
    n=nrow(mat) 
    for(i in 1:n){ 
    mat[i,] = 1.2 
    } 
} 

>system.time(testfloat(matrix(data=NA,nrow=1e4,ncol=1e4))) 
user system elapsed 
3.08 0.24 3.32 
> system.time(testfloat(matrix(data=NA_real_,nrow=1e4,ncol=1e4))) 
user system elapsed 
2.91 0.23 3.14 

A dla liczb całkowitych:

testint = function(mat){ 
    n=nrow(mat) 
    for(i in 1:n){ 
    mat[i,] = 3 
    } 
} 

> system.time(testint(matrix(data=NA,nrow=1e4,ncol=1e4))) 
user system elapsed 
2.96 0.29 3.31 
> system.time(testint(matrix(data=NA_integer_,nrow=1e4,ncol=1e4))) 
user system elapsed 
2.92 0.35 3.28 

Różnica jest niewielka w moich testów, ale to tam.

+1

'3' jest z klasy" numerycznej "prawdopodobnie oznaczało 3L. Niemniej jednak nie widzę żadnego mierzalnego wpływu na wydajność używania tylko NA (nawet jeśli mierzy się po 20 s każdy i upewnia się, że gc wykonuje swoją pracę) –

0
rows<-3 
cols<-3  
x<-rep(NA, rows*cols) 
x1 <- matrix(x,nrow=rows,ncol=cols) 
Powiązane problemy