2011-11-17 7 views
15

Chciałbym sprawdzić, czy data.frame ma żadnych elementów nieskończonych.Jak sprawdzić dane.frame dla każdego nieskończonego

Wydaje ocenić każdą kolumnę, wracając FAŁSZ dla każdego (zgaduję jego oceny data.frame jako lista):

any(!is.finite(x)) 

ja nie rozumiem, dlaczego ten zachowuje się inaczej niż powyższe , ale działa dobrze, jeśli po prostu sprawdzanie dla NA:

any(!is.na(x)) 

Chciałbym, aby rozwiązanie było tak wydajne, jak to tylko możliwe. Zdaję sobie sprawę, mogę po prostu zrobić ...

any(!is.finite(as.matrix(x))) 
+0

Wydajność jest dobra, ale ... czy masz jakiekolwiek dowody na to, że szybkość tego testu jest (lub będzie) wąskim gardłem w Twojej analizie? –

+2

Jest mało prawdopodobne, aby był wąskim gardłem. Widzę to pytanie jako okazję, aby dowiedzieć się więcej o R. Zastanawiam się, czy brakuje mi jakiejś techniki oceny elementów w data.frame, poza oczywistą techniką konwersji na inny typ danych. – SFun28

Odpowiedz

15

Jeśli wpiszesz methods(is.na) zobaczysz, że ma data.frame metodę, która prawdopodobnie wyjaśnia, dlaczego to działa zgodnie z oczekiwaniami, gdzie is.finite nie. Typowym rozwiązaniem byłoby napisanie go samemu, ponieważ jest to tylko jedna linia. Coś takiego może,

is.finite.data.frame <- function(obj){ 
    sapply(obj,FUN = function(x) all(is.finite(x))) 
} 
+0

Dzięki za wskaźnik do metod() i rozwiązanie! Użyłbym "wszystkich" zamiast "dowolnych" i zdefiniowałbym skończoną kolumnę data.frame jako kolumnę zawierającą tylko finite – SFun28

+0

@ SFun28 Dobrze, dzięki. Wpisany trochę zbyt szybko. Edytowane w celu odzwierciedlenia Twojego punktu widzenia. – joran

6

Jestem zakładając błąd otrzymujesz jest następujący:

> any(is.infinite(z)) 
Error in is.infinite(z) : default method not implemented for type 'list' 

Ten błąd jest ponieważ is.infinite() oraz funkcje is.finite() nie są realizowane w sposób dla danych .frames. Funkcja is.na() ma metodę data.frame.

Sposób obejścia tego problemu to apply() funkcja dla każdego wiersza, kolumny lub elementu w data.frame. Oto przykład z użyciem sapply() zastosować funkcję is.infinite() do każdego elementu:

x <- c(1:10, NA) 
y <- c(1:11) 
z <- data.frame(x,y) 
any(sapply(z, is.infinite)) 
## or 

any(! sapply(z, is.finite)) 
3

Jedną z różnic jest to, że is.na i is.finite są różne rodzaje funkcji. is.na jest generyczna i będzie wysyłana w oparciu o klasę argumentu.

> methods("is.na") 
[1] is.na.data.frame  is.na.numeric_version is.na.POSIXlt   
[4] is.na.raster*   

    Non-visible functions are asterisked 

Należy zwrócić szczególną uwagę na funkcję is.na.data.frame. Patrząc na tej funkcji:

> is.na.data.frame 
function (x) 
{ 
    y <- do.call("cbind", lapply(x, "is.na")) 
    if (.row_names_info(x) > 0L) 
     rownames(y) <- row.names(x) 
    y 
} 
<bytecode: 00000000054F40F0> 
<environment: namespace:base> 

część, która działa jest wezwanie do.call("cbind", lapply(x, "is.na")) co stawia kolumny razem (cbind), które są wynikiem lapply(x, "is.na"). Bieganie po prostu to na przykładzie data.frame (mtcars):

> lapply(mtcars, "is.na") 
$mpg 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

$cyl 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

$disp 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

$hp 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

$drat 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

$wt 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

$qsec 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

$vs 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

$am 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

$gear 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

$carb 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

widzimy, że jest to naprawdę tylko obliczenie kolumny mądry, umieścić z powrotem razem w data.frame.

Porównaj to is.finite, który nie ma określonej funkcji dla data.frames:

> methods("is.finite") 
no methods were found 

W rzeczywistości jest prymitywny sposób, co oznacza, że ​​dane są w postaci kodu C nie kodowania R.

> is.finite 
function (x) .Primitive("is.finite") 

Jeśli chcesz wykonać obliczenia kolumny mądry z is.finite można owinąć go jak is.na.data.frame robi.

> do.call(cbind, lapply(mtcars, is.finite)) 
     mpg cyl disp hp drat wt qsec vs am gear carb 
[1,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[2,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[3,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[4,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[5,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[6,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[7,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[8,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[9,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[10,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[11,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[12,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[13,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[14,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[15,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[16,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[17,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[18,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[19,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[20,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[21,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[22,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[23,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[24,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[25,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[26,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[27,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[28,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[29,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[30,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[31,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
[32,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 

Ten ostatni może być również zdobyć jak

sapply(mtcars, is.finite) 

Brak badań na co byłoby najbardziej skuteczne, choć.

+0

dzięki, Brian! Doceniam podział is.na.data.frame – SFun28

4

Twoje rozwiązanie wywoływania as.matrix będzie działać tylko wtedy, gdy tylko data.frame ma kolumny liczbowe. W przeciwnym razie matryca stanie się zwykle matrycą znaków, a wynik będzie fałszem wszędzie ...

@joran ma dobre podejście, ale będziesz mieć problemy z kolumnami czynników, chyba że dodasz metodę dla czynników itp. ..

is.finite(letters[1:3])   # FALSE - OK 
is.finite(factor(letters[1:3])) # TRUE - WRONG!! 

is.finite.factor <- function(obj){ 
    logical(length(obj)) 
} 

is.finite(factor(letters[1:3])) # FALSE - OK 

Ponadto, jeśli chcesz sprawdzić się tak szybko, jak to możliwe, należy unikać sapply i zamiast iść do vapply.

d <- data.frame(matrix(runif(1e6), nrow=10), letters[1:10]) 

# @joran's method 
is.finite.data.frame <- function(obj){ 
    sapply(obj,FUN = function(x) all(is.finite(x))) 
} 

system.time(x <- is.finite(d)) # 0.42 secs 

# Using vapply instead... 
is.finite.data.frame <- function(obj) { 
    vapply(obj,FUN = function(x) all(is.finite(x)), logical(1)) 
} 

system.time(y <- is.finite(d)) # 0.20 secs 

identical(x,y) # TRUE 
+0

Świetne informacje o as.matrix, kolumnach współczynników i vapply! Ta odpowiedź jest pełna dobrych rzeczy. =) – SFun28

Powiązane problemy