2010-11-14 5 views
1

Ok, le titre peut ne pas être le plus descriptif. C'est plus facile à expliquer avec un exemple.R: Sélectionnez des cellules dans data.frame en fonction d'un autre attribut dans la même instance

J'ai un data.frame comme ceci:

A B 1 2 
L M 3 0 
P Q 5 6 

Je veux sortir un tableau de la cellule dans la colonne 1 si col3> col4, ou la cellule col2 si col3 < = col4. Le vecteur de sortie de ce data.frame serait B, L, Q.

Je suis conscient que je n'ai pas encore très bien expliqué mon problème, voici donc ce qu'il ressemblerait dans un langage impératif:

vector = [] 
for each rows as row 
    if row[3] > row[4] 
    vector.add(row[1]) 
    else 
    vector.add(row[2]) 
return vector 

Je suis désolé si ce problème a déjà répondu, mais malheureusement Google n'est pas beaucoup d'aide quand il s'agit de questions R.

Merci, Andreas

Répondre

3

Cela devrait fonctionner (en supposant df est votre trame de données)

apply(df, 1, function(x){ifelse(x[3] > x[4], x[1], x[2])}) 
+3

'ifelse' est vectorisé donc' ifelse (df [[3]]> df [[4]], df [[1]], df [[2]]) 'est suffisant. – Marek

+0

Parfait, merci! –

4

Votre cas de test n'est pas suffisamment complexe pour exposer quelques-uns des crocodiles rôdent dans la R concernant les objets de class == factor, options par défaut pour data.frame(), et l'utilisation de fonctions comme apply et ifelse. Je pourrais m'excuser pour la longueur de la réponse, mais c'est vraiment juste un petit sous-ensemble de ce que vous pouvez lire en The R Inferno. Disons que vous créez un data.frame, MRJF:

dfrm <-data.frame(textConnection("A B 2 12 
L M 3 0 
P Q 5 6", header=FALSE) 

AVIS: Je modifié votre premier cas, un peu. Exécutez maintenant la première solution proposée: vous obtenez

apply(dfrm, 1, function(x){ifelse(x[3] > x[4], x[1], x[2])}) 
[1] "A" "L" "P" 

Clairement 2 n'est PAS supérieur à 12, alors que s'est-il passé? La fonction apply fonctionne sur les matrices et a converti le data.frame en matrice avant de faire la fonction et testé "2"> "12" qui est TRUE. Donc, le crocodile # 1 est le comportement par défaut de apply().

erreurs ou avertissements résultent également de ce qui pourrait sembler au premier et deuxième coup d'œil pour être parfaitement raisonnable code R:

vector <- dfrm$V2; 
vector[V3 > V4] <- V1[V3 > V4] 

(Il n'a pas été un message d'erreur particulièrement instructif, pour moi en tout cas, ... quelque chose à propos de NA ... et c'était dû au fait que j'essayais d'assigner une valeur à un objet facteur pour lequel il n'y avait pas de niveau existant.) C'est le deuxième crocodile: la classe par défaut pour les valeurs de caractères données à la fonction data.frame est "facteur" plutôt que "caractère".

Le troisième crocodile est le comportement de ifelse:

with(dfrm, ifelse(V3 > V4, V1, V2)) 
[1] 1 2 3 

WTF? La fonction ifelse convertit automatiquement les facteurs dans V1 et V2 en leurs représentations numériques internes et cela parce que la fonction contraint les valeurs retournées sur la base du type des arguments conditionnels. Pas la façon dont j'aurais conçu une telle fonction, mais ces choses ont été élaborées il y a des décennies, donc les changer est presque impossible.Ainsi, un couple de "droit", ou du moins plus sûr, les moyens de faire le travail que vous avez demandé: Method1:

with(dfrm, ifelse(V3 > V4, as.character(V1), as.character(V2))) 
[1] "B" "L" "Q" 

Method2:

vector <- as.character(dfrm$V2) 
vector[which(dfrm$V3 > dfrm$V4)] <- as.character(dfrm$V1[which(dfrm$V3 > dfrm$V4)]) 
vector 
[1] "B" "L" "Q" 
Questions connexes