2014-05-12 3 views
0

Je suis un nouvel utilisateur de R et je ne sais pas très bien comment améliorer le script suivant. J'ai entendu parler des fonctions d'application mais je n'ai pas réussi à les utiliser. Voici mon problème:Eviter la boucle for en utilisant une fonction apply

J'ai deux dataframes, la première appelée data et la seconde eco. data a plus de 1 million de lignes et eco 90.000. Ils ont tous les deux une colonne commune nommée id .Pour l'un id, il y a plusieurs rangées en data correspondant à la présence d'espèces botaniques.

Je veux symplify en donnant une valeur à la id dans la trame de données eco si une espèce spécifique est présente ou manquant dans le même id dans data. L'information apparaîtra dans une colonne sp dans eco.

Mon script avec la boucle for, qui prend des heures à courir:

for (k in (1:nrow(data))) { 
if (data[k, "sp"]==1) #sp corresponds to one specific specie 
{ 
eco[which(eco$id==data[k, "id"]), "sp"] = 1 # before this, the "sp" columnis empty in eco 
} 
} 

Comment puis-je améliorer cela?

Merci beaucoup pour votre aide.

Répondre

1

Est-ce ce que vous cherchez?

Modifier après commentaire par @Simon:

eco$sp <- 0       #create new column `sp` initialized with 0 
eco[eco$id %in% data$id[data$sp == 1],"sp"] <- 1 # replace 0 with 1 if for all id where data$sp == 1 
+0

@ SimonO'Hanlon merci pour le commentaire. J'ai mis à jour ma réponse –

+0

C'est ce que je cherchais. Merci beaucoup, ça ne prend pas de temps pour courir! – user3443183

2

Avec 1.000.000 dossiers je voudrais envisager d'utiliser data.table. Vous pouvez le faire en utilisant l'une des opérations de jointures composites de data.table, qui est juste data[sp==1,][eco], si cela ne vous dérange pas NA étant renvoyé lorsque l'espèce 1 n'est pas présente. Vous avez la configuration parfaite. Deux tables avec une clé commune. Vous pouvez facilement le faire comme ceci:

# Some sample data 
set.seed(123) 
data <- data.frame(id = rep(letters[1:3] , each = 3) , sp = sample(1:5 , 9 , TRUE)) 
eco <- data.frame(id = letters[1:3] , otherdat = rnorm(3)) 
data 
    id sp 
#1: a 2 
#2: a 4 
#3: a 3 
#4: b 5 
#5: b 5 
#6: b 1 ===> species 1 is present at this id only 
#7: c 3 
#8: c 5 
#9: c 3 

eco 
# id otherdat 
#1: a -0.1089660 
#2: b -0.1172420 
#3: c 0.1830826 


# All you need to do is turn your data.frames to data.tables, with a key, like so... 
require(data.table) 
data <- data.table(data , key = "id") 
eco <- data.table(eco , key = "id") 

# Join relevant records from data to eco by the common key 
# This way keep 0 when species 1 is present and 0 otherwise 
eco[ data[ , list(sp = as.integer(any(sp == 1))) , by = id ] ] 
# id otherdat sp 
#1: a -0.1089660 0 
#2: b -0.1172420 1 
#3: c 0.1830826 0 

# A more succinct way of doing this (and faster) 
# is a compound join (but you get NA instead of 0) 
data[sp==1,][eco] 
# id sp otherdat 
#1: a NA -0.1089660 
#2: b TRUE -0.1172420 
#3: c NA 0.1830826 
+0

Merci beaucoup, ça marche parfaitement bien. – user3443183

Questions connexes