2016-06-29 12 views
10

Jestem zainteresowany identyfikacji skalary numerycznych jak:Jak sprawdzić skalar w R?

doub <- 3.14 
intg <- 8L 

wiem, że są one traktowane jako długość jednego wektorów. Tak więc dla każdego obiektu R x jest właściwy sposób sprawdzenia, czy x jest skalarem? length(x) == 1 samo w sobie nie jest wystarczające, ponieważ zwraca wartość true, gdy zwraca false, dla ramki danych z jedną kolumną lub listy z jednym elementem.

Czy istnieje powód, dla którego nie ma takiej funkcji is.scalar zaimplementowanej w bazie R? Z jakiegoś powodu dwa udało mi się znaleźć w innych funkcji fail dla przypadku ramki danych wspomniano wcześniej, są to:

assertthat::is.scalar(data.frame(a = 1:2)) 
lambda.tools::is.scalar(data.frame(a = 1:2)) 

Dlaczego są wyniki tych dwóch wywołań funkcji różni się od mojego zrozumienia (i definicji), w jaki sposób is.scalar funkcja powinna działać?

+2

Prawdopodobnie chcesz 'is.atomic' zamiast' is.vector'. –

+2

jaka jest różnica między tymi dwoma? – Alex

+0

Zobacz '? Is.atomic':" Powszechnie nazywa się typy atomowe "wektory atomowe ', ale zauważ, że' jest.vector' nakłada dodatkowe ograniczenia: obiekt może być atomowy, ale nie wektorowy (w tym sensie). " – MichaelChirico

Odpowiedz

8

Myślę, że is.atomic odpowiada Twoim potrzebom.

dlaczego is.vector jest prawdopodobnie niezgodna, patrz np:

is.atomic(list(1)) 
# [1] FALSE 

is.vector(list(1)) 
# [1] TRUE 

Na swoich obiektów:

is.scalar <- function(x) is.atomic(x) && length(x) == 1L 

is.scalar(doub) 
# [1] TRUE 

is.scalar(intg) 
# [1] TRUE 

is.scalar(c(doub, intg)) 
# [1] FALSE 
8

budynek na answer przez @MichaelChirico, istnieje kilka innych rzeczy, które is.scalar() powinien sprawdzić.

Po pierwsze, liczby zespolone nie są zwykle uważane za skalary (chociaż myślę, że to użycie może się różnić w zależności od dyscypliny).

comp <- 2+3i 
is.scalar <- function(x) is.atomic(x) && length(x) == 1L 
is.scalar(comp) 
# TRUE 

więc powinniśmy również sprawdzić liczby zespolone. Prosty, ale naiwny sposób, aby to zrobić jest użycie is.complex

is.scalar <- function(x) is.atomic(x) && length(x) == 1L && !is.complex(x) 
is.scalar(comp) 
# FALSE 

Niestety, to nie jest całkiem w porządku, bo is.complex tylko sprawdza, czy klasa jest "complex". Ale liczby rzeczywiste mogą mieć klasę = złożoną, jeśli ich wyimaginowany komponent wynosi zero.

is.complex(2+0i) 
# [1] TRUE 

Więc przetestować dla liczb rzeczywistych jesteśmy lepiej sprawdzić, czy urojona składowa wynosi zero używając Im(x)==0. Tak, to prowadzi nas do testu dla skalarów, które wyglądają jak to

is.scalar <- function(x) is.atomic(x) && length(x) == 1L && Im(x)==0 

Więcej trywialnie, znaków powinien również zostać wyeliminowane

is.scalar("x") 
# TRUE 
is.scalar <- function(x) is.atomic(x) && length(x) == 1L && !is.character(x) && Im(x)==0 
is.scalar("x") 
# FALSE 

pamiętać, że przetestowania dla is.character(x) przed Im(x)==0 tak że leniwa ewaluacja gwarantuje, że funkcja nigdy nie próbuje znaleźć wyimaginowanej składowej postaci, która spowodowałaby błąd.

+0

Dlaczego więc nie po prostu użyć 'is.scalar <- function (x) length (x) == 1L && is.vector (x, mode =" numeric ")'? – Wastl

+1

@Wastl To zależy od celu i exaclty, co chcesz przetestować, ale przy użyciu definicji 'is.scalar (x)' nie powiedzie się np. 'x = 1 + 0i',' x = NA' i 'x = 1; attr (x, 'foo') = 1' – dww

Powiązane problemy