2013-01-05 10 views
21

Ich habe ein Array:Interpretieren "Zustand hat Länge> 1" Warnung von `if` Funktion

a <- c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 

und mag die folgende Funktion implementieren:

w<-function(a){ 
    if (a>0){ 
    a/sum(a) 
    } 
    else 1 
} 

Diese Funktion möchte Überprüfen Sie, ob ein Wert in a größer als 0 ist und wenn ja, teilen Sie jedes Element durch die Summe der Summe.

aufnehmen sollte es sonst nur 1.

ich die folgende Warnmeldung erhalten:

Warning message: 
In if (a > 0) { : 
the condition has length > 1 and only the first element will be used 

Wie kann ich die Funktion korrekt? vielleicht

+0

@ user1723765 was erwarten Sie als Ergebnis? – agstudy

+1

also grundsätzlich wenn aa [a> 0] dann a/sum (a) sollte getan werden, nicht a [0]/sum (a) – user1723765

+0

das Ergebnis wäre 0s und .166667 usw. für die anderen Zahlen, aber ich würde habe immer noch den ganzen Vektor am Ende – user1723765

Antwort

37

Sie ifelse:

a <- c(1,1,1,1,0,0,0,0,2,2) 
ifelse(a>0,a/sum(a),1) 

[1] 0.125 0.125 0.125 0.125 1.000 1.000 1.000 1.000 
[9] 0.250 0.250 
30

if Aussage nicht vektorisiert wird. Für vektorisierte if-Anweisungen sollten Sie ifelse verwenden. In Ihrem Fall ist es ausreichend,

w <- function(a){ 
if (any(a>0)){ 
    a/sum(a) 
} 
    else 1 
} 

oder eine kurze vektorisierte Version

ifelse(a > 0, a/sum(a), 1) 

Es davon abhängt, welche zu schreiben tun Sie verwenden möchten, weil erste Funktion Ausgangsvektor der Länge 1 (in anderen Teil gibt) und ifelse gibt den Ausgangsvektor der Länge gleich der Länge a.

+10

warum oh warum, wenn alles andere im R-land vektorisiert ist ... 'wenn' nicht? Smdh. –

14

Hier ist eine einfache Möglichkeit, ohne ifelse:

(a/sum(a))^(a>0) 

Ein Beispiel:

a <- c(0, 1, 0, 0, 1, 1, 0, 1) 

(a/sum(a))^(a>0) 

[1] 1.00 0.25 1.00 1.00 0.25 0.25 1.00 0.25 
+4

Dies schlägt 'ifelse' um etwa einen Faktor von 7 (auf einem Array von 100000 Elementen). –

+0

Gut zu wissen, @Arun +1 –

+0

Können Sie eine kurze Erklärung/Dokumentation dieses '^' Operators empfehlen (z. B. wie es heißt und wie es funktioniert). Vorzugsweise etwas einfacher als die [Arithmetische Operatoren] (https://stat.ethz.ch/R-manual/R-devel/library/base/html/Arithmetic.html) Dokumentation ... – theforestecologist

7

gerade hinzufügen, um einen Punkt zu der ganzen Diskussion darüber, warum diese Warnung kommt (Es war nicht klar, ich vorher). Der Grund dafür ist, wie bereits erwähnt, der Fall, weil 'a' in diesem Fall ein Vektor ist und die Ungleichung 'a> 0' einen anderen Vektor von TRUE und FALSE erzeugt (wobei 'a'> 0 ist oder nicht).

Wenn Sie möchten, anstatt testen, ob irgendein Wert von ‚a> 0‘ können Sie Funktionen verwenden - ‚any‘ oder ‚all‘

Beste

0

So wie ich über diese Frage cam war wenn ich etwas Ähnliches versuchte, wo ich eine Funktion definierte und es mit dem Array aufgerufen wurde wie andere darauf hingewiesen

Sie könnten so etwas für diese Szenarien tun, aber es ist weniger elegant im Vergleich zu Svens Methode.

sapply(a, function(x) afunc(x)) 

afunc<-function(a){ 
    if (a>0){ 
    a/sum(a) 
    } 
    else 1 
} 
Verwandte Themen