3 votes

Accélérer une boucle for R pour coller plusieurs variables ensemble

Je suis nouveau ici mais j'ai besoin d'aide. J'ai une liste de cadres de données, et pour chaque élément de ma liste (c'est-à-dire data.frame), je veux coller rapidement une colonne d'un ensemble de données vers plusieurs autres colonnes du même ensemble de données, séparées uniquement par un point (".").

Donc si j'ai un ensemble de données dans une liste de cadres de données :

list1[[1]]

A  B  C
2  1  5
4  2  2

Je veux alors le résultat suivant :

list1[[1]]

 A    B   C
2.5  1.5  5
4.2  2.2  2  

Où C est collé à A et B individuellement. Je veux ensuite que cette opération ait lieu pour chaque cadre de données de ma liste.

J'ai essayé ce qui suit :

pasteX<-function(df) {for (i in 1:dim(df)[2]-1) {
df[,i]<-as.numeric(sprintf("%s.%s", df[,i], df$C))
}
return(df)}
list2<-lapply(list1, pasteX)

Mais cette approche est très lente pour les matrices et les listes de grande taille. Avez-vous des recommandations pour rendre ce code plus rapide ? Merci !

1 votes

Bienvenue. Idéalement, fournissez vos données d'une manière plus facile à lire : stackoverflow.com/questions/5963269/

2 votes

Ah, merci d'avoir partagé cela... Je ferai plus attention à la façon dont je présente mes données et mes questions à partir de maintenant !

4voto

RyanD Points 6857

En supposant que tout est des entiers < 10

lapply(list1, function(x){
    x[,-3] <- x[,-3] + x[,3]/10
    x})

3voto

akrun Points 148302

Nous pouvons utiliser Map

list1[[1]][-3] <- Map(function(x, y) as.numeric(sprintf('%s.%s', x, y)), 
                     list1[[1]][-3], list1[[1]][3])

S'il y a beaucoup d'ensembles de données, bouclez en utilisant lapply convertir les deux premières colonnes en matrix et coller avec la troisième colonne, mettre à jour la sortie, et retourner le jeu de données

lapply(list1, function(x)  {
     x[1:2] <- as.numeric(sprintf('%s.%s', as.matrix(x[1:2]), x[,3]));
     x })
#[[1]]
#    A   B C
#1 2.5 1.5 5
#2 4.2 2.2 2

Ou en utilisant tidyverse

library(tidyverse)
map(list1, ~ .x %>%
               mutate_at(1:2, funs(as.numeric(sprintf('%s.%s', ., C)))))

Ou avec data.table

library(data.table)
lapply(list1,  function(x) setDT(x)[, (1:2) := 
     lapply(.SD, function(x) as.numeric(sprintf('%s.%s', x, C))) ,
             .SDcols = 1:2][])

0 votes

Merci, @akrun ! C'est utile, je vais essayer de mettre cela en œuvre maintenant et voir si cela me donne un coup de pouce.

0 votes

@zeekster26 Pas de problème. Si vous vérifiez les benchmarks, j'ai également mis à jour avec une méthode data.table. Veuillez vérifier cela aussi

1 votes

C'est bon ! C'est très apprécié... J'essayais une méthode data.table mais je m'y prenais un peu mal.

0voto

Essayez ceci :

df <- data.frame(a = c(1,2,3), b = c(3,2,1), c = c(2,1,1))

pastex <- function(x){
 m<-  sapply(df[,1:2], function(x) as.numeric(paste(x, df$c, sep = '.')))
 m <- as.data.frame(m)
 m <- cbind(m, df["c"])
 return(m)
}

mylist <- list(df1 = df, df2 = df)

lapply(mylist, pastex)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X