1
votes

purrr itérer ou faire une boucle sur toutes les colonnes (similaire à la fonction qui compte et additionne ou soustrait des variables)

Je voudrais trouver ici quelques idées pour résoudre un problème très pratique. Disons que j'ai deux points temporels (w0 et w1) et que je veux soustraire (ou additionner) toutes les valeurs appariées spécifiques. Mesurez 1 au temps 1 et mesurez 1 au temps 2, mesurez 2 au temps 1 et mesurez 2 au temps 2.

Je suis plus familier avec l'environnement tidyverse (le ronronnement sera souhaitable) et c'est le code que j'ai pour simuler le ensemble de données réel

Toute chasse est souhaitée. Merci

for (i in 1:3) {
  ds %>% 
    summarise(dif_1 = mean(w0_[[i]], na.rm=T)-mean(w1_[[i]], na.rm=T))
}

Au fait, je sais que le code suivant ne fonctionnera pas, mais c'est la raison d'être de ma question

library(tidyverse)
ds <- data.frame(w0_1=rnorm(10,1,2),
                 w0_2=rnorm(10,3,3),
                 w0_3=rnorm(10,3,2),
                 w1_1=rnorm(10,2,1),
                 w1_2=rnorm(10,3,3),
                 w1_3=rnorm(10,5,4))


ds %>% 
  summarise(dif_1 = mean(w0_1, na.rm=T)-mean(w1_1, na.rm=T))

ds %>% 
  summarise(dif_2 = mean(w0_2, na.rm=T)-mean(w1_2, na.rm=T))


0 commentaires

3 Réponses :


1
votes

Voici une solution, il y a probablement quelque chose de plus simple

ds %>% pivot_longer(names(ds),names_to=c('g0','g1'),names_pattern= '^(w.*)_(.*)') %>% # convert to long format
       group_by(g0,g1) %>% # group by g0 = (w0 or w1) and g1=(1,2,3)
       summarise(value=mean(value,na.rm=TRUE))   %>% # get mean by group
       pivot_wider(names_from=g0,values_from=value) %>% # pivot to get three lines
       mutate(dif = w0-w1) %>% # difference of mean by group
       select(g1,dif) %>% # keep only useful columns
       pivot_wider(names_from=g1,names_prefix='dif_',values_from=dif) #pivot again to have everything in one line

# A tibble: 1 x 3
#  dif_1 dif_2 dif_3
#  <dbl> <dbl> <dbl>
#1 -0.856 0.344  -2.84

Vous n'avez pas défini de graine donc nos résultats peuvent varier, j'ai utilisé set.seed (1) code >.

Aucune boucle ou besoin de ronronnement, l'idée est que si vous devez faire des boucles, cela signifie que vos données doivent être remodelées en utilisant pivot_longer par exemple

Je vous suggère de l'exécuter étape par étape pour voir ce que fait le code sur chaque ligne, chaque étape est une transformation de base.


3 commentaires

La moyenne pour w0_1 est 1.264 et pour w1_1 est 2.121 donc w0_1 - w1_1 est -.856.


@dcarlson très bien merci, je faisais w1-w0 au lieu de w0-w1


Wow, merci beaucoup. C'est une solution très élégante. Il me manquait dplyr utilise maintenant pivot_longer (au lieu de rassembler / diffuser). Maintenant, j'essaye de comprendre l'argument "names_to".



2
votes

En utilisant les données de @ fmarm, voici une approche non ordonnée:

(ds.diff <- ds.mean[1:3] - ds.mean[4:6])
#    w0_1    w0_2    w0_3 
# -0.8563  0.3441 -2.8412

Si le nombre de w0 est connu (3 dans ce cas), c'est plus simple:

XXX


2 commentaires

Réponse beaucoup plus simple que la mienne, +1


Solution très agréable et facile! Merci beaucoup !! +1



1
votes

Pour une approche purrr , vous pouvez d'abord diviser le dataframe en groupes de 3, puis utiliser pmap_dbl ()

dataset %>% 
  select(starts_with("w4"), starts_with("w0")) %>%
  split.default((seq_along(.)-1) %/% (ncol(.)/2)) %>%
  pmap_dbl(~ mean(.x - .y))

Dans réponse aux commentaires de l'OP concernant l'ensemble de données complet comportant 12 variables aux deux points temporels, et en supposant que les variables sont dans l'ordre et n'ont aucune valeur manquante:

library(purrr)
library(dplyr)

split.default(ds, (seq_along(ds)-1) %/% 3) %>%
  pmap_dbl(~ mean(.x - .y))

      w0_1       w0_2       w0_3 
-0.8563246  0.3441249 -2.8411739 


5 commentaires

Merci beaucoup, mais si au lieu d'avoir un ds, je dois sélectionner certaines variables, telles que w0_1: w0_3, w1_1: w1_3. Ceci -> split.default (ds, select (w0_1: w0_3, w1_1: w1_3))%>% pmap_dbl (~ mean (.x - .y)) ne fonctionne pas.


OK - vous devez simplement sélectionner les variables avant de fractionner - ds%>% select (starts_with ("w0"), starts_with ("w1")) ...


Merci. J'y suis presque. Dans mon ensemble de données réel, j'ai 12 variables pour la première mesure et 12 variables pour la seconde. C'est proche, mais il se passe quelque chose. Pourriez-vous s'il vous plaît corriger ce qui suit? Merci. ensemble de données%>% select (starts_with ("w4"), starts_with ("w0"))%>% split.default (., (seq_along (.) - 1)% /% 3)%>% pmap_dbl (~ mean ( .x - .y))


La dernière question, au cas où il me manquerait des données, les résultats peuvent être délicats: pmap_dbl (~ mean (.x - .y, na.rm = T)) semble fonctionner, mais je ne sais pas si les résultats sont fiables .


@Luis - Avec des valeurs manquantes, vous pouvez le changer en mean (.x, na.rm = TRUE) - mean (.y, na.rm = TRUE) .