Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Helene Charpentier
Messages : 13
Enregistré le : 04 Mar 2019, 16:09

Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Helene Charpentier » 04 Mar 2019, 17:04

Bonjour et désolée pour le titre, j'ai pas su condenser clairement...

1/ Je débute complètement (depuis une semaine)
2/ Je vous juuure que j'ai cherché (17 heures juste pour cette fonction), et rien à faire, je tourne en rond (et commence à jeter des feuilles et des livres partout par terre en m'arrachant des cheveux)

3/ Voilà ce que j'aimerais faire :
- J'ai un tableau avec plein de pays, des années (Panel, donc), des taux d'émissions de CO2 (et le reste - pas utile pour la question)
- J'essaye d'obtenir une liste sans doublon de pays pour lesquels les taux d'émissions de CO2 sont des valeurs aberrantes.
- Pourquoi des doublons ? Parce que, par exemple, pour Algérie, j'ai une ligne Algérie 1990 etc puis Algérie 1991, ... et ainsi de suite jusqu'en 2014 et pour tous les pays comme ça.

4/ Voilà mon code (tout moche) (désolée, je suis archi débutante)

Code : Tout sélectionner

library(readxl)
ChocsEtCO2_Base <- read_excel("C:/Users/OXFAM/Desktop/Lyon - 2nd semester/E&E/W groupe/Bases/Bonne Base/ChocsEtCO2_Base.xlsx",
                              col_types = c("text", "text", "numeric",
                                            "numeric", "numeric", "numeric", "numeric",
                                            "numeric","numeric", "numeric", "numeric",
                                            "numeric", "numeric", "numeric", "numeric",
                                            "numeric", "numeric", "numeric", "numeric",
                                            "numeric", "numeric", "numeric","numeric",
                                            "numeric", "numeric", "numeric","numeric",
                                            "numeric","numeric", "numeric"),
                                             na = "..")

warnings()
# Erreur non importante : il s'agit de la colonne "Country Code"
# On renomme les colonnes
# Recherche de la formule
?setNames
colnames(ChocsEtCO2_Base)
colnames(ChocsEtCO2_Base) <- c("Pays", "CodePays", "Annee", "CodeAnnee",
                                "Catastrophes", "Inflation", "CO2", "Agriculture",
                                "Dette", "Charbon", "DepSante", "Rentesforet", "IDEentr",
                                "IDEsort", "PIB2010", "PIB2011", "DepPub",
                                "InflationDeflPIB", "RentesGaz", "RentesPetrole",
                                "ServicesPIB", "Taxes", "OuvCciale", "ServicesComm",
                                "PopRur", "PopTot", "PopUrb", "ZoneUrb", "Chomage",
                                "Corrupt")

# Boîtes à moustaches
install.packages("rpart")
library(rpart)
boxplot(ChocsEtCO2_Base$Catastrophes,col="purple",main="Catastrophes Naturelles")
boxplot(ChocsEtCO2_Base$Inflation,col="purple",main="Inflation")
boxplot(ChocsEtCO2_Base$CO2,col="purple",main="Émissions de CO2")
boxplot(ChocsEtCO2_Base$Agriculture,col="purple",main="Agriculture, Forêt, Pêche")
boxplot(ChocsEtCO2_Base$Dette,col="purple",main="Dette Publique")
boxplot(ChocsEtCO2_Base$Charbon,col="purple",main="Charbon")
boxplot(ChocsEtCO2_Base$DepSante,col="purple",main="Dépenses de santé")
boxplot(ChocsEtCO2_Base$Rentesforet,col="purple",main="Rentes forestières")
boxplot(ChocsEtCO2_Base$IDEentr,col="purple",main="IDE entrants")
boxplot(ChocsEtCO2_Base$IDEsort,col="purple",main="IDE sortants")
boxplot(ChocsEtCO2_Base$PIB2010,col="purple",main="PIB $2010 constant")
boxplot(ChocsEtCO2_Base$PIB2011,col="purple",main="PIB $2011 constant")
boxplot(ChocsEtCO2_Base$DepPub,col="purple",main="Dépenses publiques pour l'éducation")
boxplot(ChocsEtCO2_Base$InflationDeflPIB,col="purple",main="Inflation (PIB deflator)")
boxplot(ChocsEtCO2_Base$RentesGaz,col="purple",main="Rentes Gaz")
boxplot(ChocsEtCO2_Base$RentesPetrole,col="purple",main="Rentes Pétrole")
boxplot(ChocsEtCO2_Base$ServicesPIB,col="purple",main="Part des services")
boxplot(ChocsEtCO2_Base$Taxes,col="purple",main="Taxes")
boxplot(ChocsEtCO2_Base$OuvCciale,col="purple",main="Ouverture Commerciale")
boxplot(ChocsEtCO2_Base$ServicesComm,col="purple",main="Échanges en services")
boxplot(ChocsEtCO2_Base$PopRur,col="purple",main="Population Rurale")
boxplot(ChocsEtCO2_Base$PopTot,col="purple",main="Population Totale")
boxplot(ChocsEtCO2_Base$PopUrb,col="purple",main="Population Urbaine")
boxplot(ChocsEtCO2_Base$ZoneUrb,col="purple",main="Zone Urbaine")
boxplot(ChocsEtCO2_Base$Chomage,col="purple",main="Chômage")
boxplot(ChocsEtCO2_Base$Corrupt,col="purple",main="Indice de Corruption")

# Pour avoir plusieurs boîtes à moustaches sur la même feuille on utilise par
par (mfrow=c(2,2))
boxplot(ChocsEtCO2_Base$Catastrophes,col="purple",main="Catastrophes Naturelles")
boxplot(ChocsEtCO2_Base$Inflation,col="purple",main="Inflation")
boxplot(ChocsEtCO2_Base$CO2,col="purple",main="Émissions de CO2")
boxplot(ChocsEtCO2_Base$Agriculture,col="purple",main="Agriculture, Forêt, Pêche")
boxplot(ChocsEtCO2_Base$Dette,col="purple",main="Dette Publique")
boxplot(ChocsEtCO2_Base$Charbon,col="purple",main="Charbon")
boxplot(ChocsEtCO2_Base$DepSante,col="purple",main="Dépenses de santé")
boxplot(ChocsEtCO2_Base$Rentesforet,col="purple",main="Rentes forestières")
boxplot(ChocsEtCO2_Base$IDEentr,col="purple",main="IDE entrants")
boxplot(ChocsEtCO2_Base$IDEsort,col="purple",main="IDE sortants")
boxplot(ChocsEtCO2_Base$PIB2010,col="purple",main="PIB $2010 constant")
boxplot(ChocsEtCO2_Base$PIB2011,col="purple",main="PIB $2011 constant")
boxplot(ChocsEtCO2_Base$DepPub,col="purple",main="Dépenses publiques pour l'éducation")
boxplot(ChocsEtCO2_Base$InflationDeflPIB,col="purple",main="Inflation (PIB deflator)")
boxplot(ChocsEtCO2_Base$RentesGaz,col="purple",main="Rentes Gaz")
boxplot(ChocsEtCO2_Base$RentesPetrole,col="purple",main="Rentes Pétrole")
boxplot(ChocsEtCO2_Base$ServicesPIB,col="purple",main="Part des services")

# Pour les valeurs aberrantes, on utilise $out
IDE_in <- boxplot(ChocsEtCO2_Base$IDEentr,col="purple",main="IDE entrants")
IDE_aberrant <- IDE_in$out
IDE_aberrant

# Choix des boîtes que je garde et que j'explique
par(mfrow=c(2,5))

boxplot(ChocsEtCO2_Base$Catastrophes,col="purple",main="Catastrophes Naturelles")
boxplot(ChocsEtCO2_Base$Inflation,col="purple",main="Inflation")
boxplot(ChocsEtCO2_Base$CO2,col="purple",main="Émissions de CO2")
boxplot(ChocsEtCO2_Base$Agriculture,col="purple",main="Agriculture, Forêt, Pêche")
boxplot(ChocsEtCO2_Base$Dette,col="purple",main="Dette Publique")
boxplot(ChocsEtCO2_Base$Charbon,col="purple",main="Charbon")
boxplot(ChocsEtCO2_Base$DepSante,col="purple",main="Dépenses de santé")
boxplot(ChocsEtCO2_Base$Rentesforet,col="purple",main="Rentes forestières")
boxplot(ChocsEtCO2_Base$IDEentr,col="purple",main="IDE entrants")
boxplot(ChocsEtCO2_Base$IDEsort,col="purple",main="IDE sortants")

boxplot(ChocsEtCO2_Base$PIB2010,col="purple",main="PIB $2010 constant")
boxplot(ChocsEtCO2_Base$PIB2011,col="purple",main="PIB $2011 constant")
boxplot(ChocsEtCO2_Base$DepPub,col="purple",main="Dépenses publiques pour l'éducation")
boxplot(ChocsEtCO2_Base$InflationDeflPIB,col="purple",main="Inflation (PIB deflator)")
boxplot(ChocsEtCO2_Base$RentesGaz,col="purple",main="Rentes Gaz")
boxplot(ChocsEtCO2_Base$RentesPetrole,col="purple",main="Rentes Pétrole")
boxplot(ChocsEtCO2_Base$ServicesPIB,col="purple",main="Part des services")
boxplot(ChocsEtCO2_Base$Taxes,col="purple",main="Taxes")
boxplot(ChocsEtCO2_Base$OuvCciale,col="purple",main="Ouverture Commerciale")
boxplot(ChocsEtCO2_Base$ServicesComm,col="purple",main="Échanges en services")

boxplot(ChocsEtCO2_Base$PopRur,col="purple",main="Population Rurale")
boxplot(ChocsEtCO2_Base$PopTot,col="purple",main="Population Totale")
boxplot(ChocsEtCO2_Base$PopUrb,col="purple",main="Population Urbaine")
boxplot(ChocsEtCO2_Base$ZoneUrb,col="purple",main="Zone Urbaine")
boxplot(ChocsEtCO2_Base$Chomage,col="purple",main="Chômage")
boxplot(ChocsEtCO2_Base$Corrupt,col="purple",main="Indice de Corruption")

# Ce qu'on a trouvé dans la littérature
# Puisque de toute façon il nous faut faire une comparaison
# Inutile à ce stade d'ajouter des variables (sans littérature)

# État, Institution, etc
par(mfrow=c(2,2))

boxplot(ChocsEtCO2_Base$PIB2010,col="blue",main="PIB $2010 constant")
boxplot(ChocsEtCO2_Base$InflationDeflPIB,col="blue",main="Inflation (PIB deflator)")
boxplot(ChocsEtCO2_Base$Corrupt,col="blue",main="Indice de Corruption")
boxplot(ChocsEtCO2_Base$Chomage,col="blue",main="Chômage")

# Urbanisation
par(mfrow=c(1,2))

boxplot(ChocsEtCO2_Base$PopTot,col="pink",main="Population Totale")
boxplot(ChocsEtCO2_Base$PopUrb,col="pink",main="Population Urbaine")

# Ouverture Commerciale et IDE
par(mfrow=c(2,2))

boxplot(ChocsEtCO2_Base$IDEentr,col="green",main="IDE entrants")
boxplot(ChocsEtCO2_Base$IDEsort,col="green",main="IDE sortants")
boxplot(ChocsEtCO2_Base$OuvCciale,col="green",main="Ouverture Commerciale")

# Émissions de CO2
par(mfrow=c(1,1))

boxplot(ChocsEtCO2_Base$IDEentr,col="grey",main="Émissions de CO2")


# Retour aux valeurs aberrantes, on utilise $out
bCO2 <- boxplot(ChocsEtCO2_Base$IDEentr,col="grey",main="Émissions de CO2")
abCO2 <- bCO2$out
abCO2

# Recherche d'une fonction pour renvoyer l'identifiant correspondant pour chaque
# valeur aberrante
# Une fonction qui renvoie l'identifiant dans un tableau pour une certaine
# valeur donnée
# Ou mieux, qui renverrait directement le nom du pays !
?match
abDoublons <- If (ChocsEtCO2_Base[,"CO2"]%in%abCO2)
                ChocsEtCO2_Base[,"Pays"]
               
# Test de ma formule (sur nombres de Pays sortis)
ChocsEtCO2_Base[,"Pays"]

# Tentative avec une boucle
for (i in 0:(nrow(ChocsEtCO2_Base)) {
  if ChocsEtCO2_Base[i,"CO2"] in abCO2
  print(ChocsEtCO2_Base[i,"Pays"]
 
}

#Ça ne fonctionne pas
               
# Suppression des doublons de pays               
doublons <- which(duplicated(abDoublons))

# Modification de la formule au-dessus pour CRÉER un vecteur qui
# liste tous les pays
?add1.lm
abDoublons <- If (ChocsEtCO2_Base[,"CO2"]%in%abCO2)
              add1(ChocsEtCO2_Base[,"Pays"])

abDoublons <- add1(If (ChocsEtCO2_Base[,"CO2"]%in%abCO2)
              (ChocsEtCO2_Base[,"Pays"])             
             
abDoublons <- list(If (ChocsEtCO2_Base[,"CO2"]%in%abCO2)
                   (ChocsEtCO2_Base[,"Pays"])
                   
abDoublons

# Blocage

liste1 <- ChocsEtCO2_Base[,"Pays"]
liste1
for ChocsEtCO2_Base[,"CO2"]%in%abCO2
  print (list(ChocsEtCO2_Base[,"Pays"]))

# Ça marche TOUJOURS PAS


Et grand mercé

Pierre-Yves Berrard
Messages : 1029
Enregistré le : 12 Jan 2016, 23:30

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Pierre-Yves Berrard » 04 Mar 2019, 18:10

Bonjour,

Quelques questions :
- à quoi sert le package rpart dans votre programme ?
- pourquoi faire des boxplot sur toutes les variables puisque seul CO2 est utile ?
PY

Pierre-Yves Berrard
Messages : 1029
Enregistré le : 12 Jan 2016, 23:30

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Pierre-Yves Berrard » 04 Mar 2019, 20:05

Une proposition quand même :

Code : Tout sélectionner

val_aberrantes <- tapply(
  ChocsEtCO2_Base$CO2,
  ChocsEtCO2_Base$Pays,
  function(x) boxplot(x, plot = FALSE)$out,
  simplify = FALSE
)

pays_aberrants <- names(val_aberrantes)[lengths(val_aberrantes) != 0]
PY

Helene Charpentier
Messages : 13
Enregistré le : 04 Mar 2019, 16:09

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Helene Charpentier » 05 Mar 2019, 05:05

Bonjour,

Merci pour votre réponse ; entre temps j'ai trouvé une bonne âme et surtout qui programme en R dans ma cité U.
Il m'a fait un petit cours et je vous laisse quand même le résultat ici :

Code : Tout sélectionner

View(unique(filter(ChocsEtCO2_Base, CO2 %in% abCO2)$Pays))
summarise(group_by(filter(ChocsEtCO2_Base, CO2 %in% abCO2), Pays), mean(CO2), min(CO2), max(CO2))


(J'ai rajouté mean, min et max, quand j'ai vu qu'avoir juste une liste de pays n'allait m'avancer à rien pour présenter à l'oral mes boîtes à moustaches sans savoir à quel pays correspondait quel point).

Et on obtient ceci :

# A tibble: 7 x 4
Pays `mean(CO2)` `min(CO2)` `max(CO2)`
<chr> <dbl> <dbl> <dbl>
1 Bulgaria 0.760 0.603 1.00
2 China 0.873 0.632 1.41
3 Qatar 0.621 0.621 0.621
4 Russian Federation 0.785 0.614 0.880
5 South Africa 0.841 0.703 0.953
6 Venezuela, RB 0.626 0.626 0.626
7 Zimbabwe 0.602 0.602 0.602


(Il est intéressant de voir que, dans les BRICS, on ne retrouve ni l'Inde ni le Brésil dans les plus gros émetteurs de CO2, mais que l'on trouve la Bulgarie par exemple.)

Merci encore pour votre aide et bonne journée :)

Helene Charpentier
Messages : 13
Enregistré le : 04 Mar 2019, 16:09

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Helene Charpentier » 05 Mar 2019, 05:09

  • Pour le rpart, je ne m'en souviens même plus, j'ai feuilleté plein de trucs, j'ai dû trouver ça quelque part...
  • Et pour tous les boxplots, c'est parce que je devais choisir les boîtes que j'allais présenter parmi toutes les variables de notre modèle à venir (et je m'entraînais à faire des boxplots) ; je cherchais la formule uniquement sur CO2, mais je vais la reprendre sur toutes les variables que j'ai gardées pour analyse.

Helene Charpentier
Messages : 13
Enregistré le : 04 Mar 2019, 16:09

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Helene Charpentier » 05 Mar 2019, 06:05

Question subsidiaire

Je me suis rendue compte que c'était long à retaper à chaque fois (et pas "joli").
Mais mon code (réécrit quelques fois déjà) ci-dessous ne fonctionne pas et je n'arrive pas à comprendre pourquoi :/

Code : Tout sélectionner

interpr <- function(n,p) {
  + res1 <- filter(ChocsEtCO2_Base, n %in% p)$Pays
  + res2 <- unique(res1)
  + res3 <- group_by(res2)
  + res4 <- summarise(res3, mean(n), min(n), max(n))
  + return(res4)
}
interpr(CO2,abCO2)


Comme ça non plus :

Code : Tout sélectionner

interpr <- function(n,p) {
  + res1 <- filter(n %in% p)$Pays
  + res2 <- unique(res1)
  + res3 <- group_by(res2)
  + res4 <- summarise(res3, mean(n), min(n), max(n))
  + return(res4)
}
interpr(CO2,abCO2)
interpr(ChocsEtCO2_Base$CO2,abCO2)

Eric Casellas
Messages : 767
Enregistré le : 06 Jan 2009, 14:59

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Eric Casellas » 05 Mar 2019, 10:42

Salut,

Helene Charpentier a écrit :Question subsidiaire
Mais mon code (réécrit quelques fois déjà) ci-dessous ne fonctionne pas et je n'arrive pas à comprendre pourquoi :/

Code : Tout sélectionner

interpr <- function(n,p) {
  + res1 <- filter(ChocsEtCO2_Base, n %in% p)$Pays
  + res2 <- unique(res1)
  + res3 <- group_by(res2)
  + res4 <- summarise(res3, mean(n), min(n), max(n))
  + return(res4)
}
interpr(CO2,abCO2)


Comme ça non plus :

Code : Tout sélectionner

interpr <- function(n,p) {
  + res1 <- filter(n %in% p)$Pays
  + res2 <- unique(res1)
  + res3 <- group_by(res2)
  + res4 <- summarise(res3, mean(n), min(n), max(n))
  + return(res4)
}
interpr(CO2,abCO2)
interpr(ChocsEtCO2_Base$CO2,abCO2)


A priori comme ça je dirai qu'il te faut enlever les + que tu as en début de ligne dans le corps de tes fonctions...

Eric
Eric

Helene Charpentier
Messages : 13
Enregistré le : 04 Mar 2019, 16:09

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Helene Charpentier » 05 Mar 2019, 11:41

Merci beaucoup pour votre aide à tous les deux !

Alors, en enlevant les '+' il me dit :

Code : Tout sélectionner

> # Creation de la fonction (bis)
> interpr <- function(n,p) {
+    res1 <- filter(n %in% p)$Pays
+    res2 <- unique(res1)
+    res3 <- group_by(res2)
+    res4 <- summarise(res3, mean(n), min(n), max(n))
+    return(res4)
+ }
> interpr(CO2,abCO2)
 Show Traceback
 
 Rerun with Debug
 Error in UseMethod("filter_") :
  no applicable method for 'filter_' applied to an object of class "logical"
>

Helene Charpentier
Messages : 13
Enregistré le : 04 Mar 2019, 16:09

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Helene Charpentier » 05 Mar 2019, 12:38

(Au pire, tant pis, on peut laisser tomber, j'ai tout fait à la main ; c'est juste par souci d' "esthétique", et de curiosité.)

Pierre-Yves Berrard
Messages : 1029
Enregistré le : 12 Jan 2016, 23:30

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Pierre-Yves Berrard » 05 Mar 2019, 12:49

Ça ressemble à un nom de fonction utilisé dans 2 packages. Remplacer filter par dplyr::filter ?
PY

Helene Charpentier
Messages : 13
Enregistré le : 04 Mar 2019, 16:09

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Helene Charpentier » 08 Mar 2019, 10:48

Il me sort encore un truc avec "logical" :

Code : Tout sélectionner

Error in UseMethod("filter_") :
  no applicable method for 'filter_' applied to an object of class "logical"


Tant pis, à mon niveau je vais tout faire manuellement ; si un jour je trouve comment en faire une fonction j'update :D

Merci beaucoup en tout cas pour le temps passé à m'aider !

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Logez Maxime » 08 Mar 2019, 13:21

Bonjour,

le problème c'est que ta fonction filter doit prendre pour premier argument un data.frame ou un tibble (etc).
Le premier argument ne peut pas être l'expression logique, n %in% p doit venir après en deuxième argument.

Cordialement,
Maxime

Helene Charpentier
Messages : 13
Enregistré le : 04 Mar 2019, 16:09

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Helene Charpentier » 08 Mar 2019, 15:10

Merci Maxime, oui je viens tout juste de voir ça sur d'autres documents (je les compte plus à force, je comprends de moins en moins et j'ai de plus en plus de mots sous R que je sais plus du tout ce que quoi veut dire)...

Donc oui, un data.frame, c'est exactement ce que je suis en train d'essayer ; j'ai fait un sous-exemple sous R pour tester ça mais comme j'ai pas eu le cours du 1er semestre, en autodidacte c'est, disons, hmm... LENT.

Je comprends plus rien.

J'avais ça, qui fonctionne trèèès bien.

Code : Tout sélectionner

# CO2
bCO2 <- boxplot(ChocsEtCO2_Base$CO2,col="grey",main="Intensité Carbone")
abCO2 <- bCO2$out
abCO2

View(unique(filter(ChocsEtCO2_Base, CO2 %in% abCO2)$Pays))
summarise(group_by(filter(ChocsEtCO2_Base, CO2 %in% abCO2), Pays), mean(CO2), min(CO2), max(CO2))


Et ça marche plus du tout quand je veux en faire une fonction :

Code : Tout sélectionner

aberr <- function(base1,col1){
  bcol1 <- boxplot(base1$col1,col="grey",main="Osef")
  abcol1 <- bcol1$out
  truc1 <- unique(filter(base1, col1 %in% abcol1)$Pays)
  truc2 <- summarise(group_by(filter(base1, col1 %in% abcol1), Pays), mean(col1), min(col1), max(col1))
  return(truc2)
}

aberr(ChocsEtCO2_Base,CO2)
aberr(ChocsEtCO2_Base,ChocsEtCO2_Base$CO2)


Ça me renvoie :

Code : Tout sélectionner

Error in plot.window(xlim = xlim, ylim = ylim, log = log, yaxs = pars$yaxs) :
  valeurs finies requises pour 'ylim'
In addition: Warning messages:
1: Unknown or uninitialised column: 'x'.
2: Unknown or uninitialised column: 'x'.
3: Unknown or uninitialised column: 'col1'.
4: In min(x) : no non-missing arguments to min; returning Inf
5: In max(x) :
 Show Traceback
 
 Rerun with Debug
 Error in plot.window(xlim = xlim, ylim = ylim, log = log, yaxs = pars$yaxs) :
  valeurs finies requises pour 'ylim'


et un début de crise de panique.

[EDIT] Je viens de voir que j'avais pas mis le truc avec le data.frame :

Code : Tout sélectionner

aberr <- function(data.frame=base1,col1){
  bcol1 <- boxplot(base1$col1,col="grey",main="Osef")
  abcol1 <- bcol1$out
  truc1 <- unique(filter(base1, col1 %in% abcol1)$Pays)
  truc2 <- summarise(group_by(filter(base1, col1 %in% abcol1), Pays), mean(col1), min(col1), max(col1))
  return(truc2)
}


Je comprends plus rien et je comprends rien à la syntaxe et ALED.

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Mickael Canouil » 08 Mar 2019, 15:25

Bonjour,

Pour rebondir sur la réponse de Maxime:

Code : Tout sélectionner

?base::filter
?dplyr::filter


Votre code contient quelques problèmes:
    "ChocsEtCO2_Base" est une variable globale dans votre fonction. C'est-à-dire, que l'objet de provient pas des arguments => Dangereux
    "CO2" est un vecteur qui n'a pas de lien avec "ChocsEtCO2_Base" après l'affectation. Indépendance des deux objets

Je vais essayer dans la suite de vous montrez en quoi ce sont des problèmes.
1/ Commençons par générer un faux jeux de données proche du votre (ou suffisamment).

Code : Tout sélectionner

library(tidyverse)
set.seed(08032019)
ChocsEtCO2_Base0 <- dplyr::tibble(
  Pays = rep(LETTERS, each = 10),
  CO2 = rnorm(length(Pays))
)
ChocsEtCO2_Base0
#> # A tibble: 260 x 2
#>    Pays      CO2
#>    <chr>   <dbl>
#>  1 A      1.05 
#>  2 A      0.888
#>  3 A     -0.460
#>  4 A     -0.217
#>  5 A     -0.961
#>  6 A     -0.0877
#>  7 A      0.593
#>  8 A      1.02 
#>  9 A     -0.0509
#> 10 A     -1.92 
#> # … with 250 more rows


2/ Créons maintenant les variables "CO2" et "abCO2" que vous utilisez

Code : Tout sélectionner

# Création d'un seuil pour exclure/inclure que certaines valeurs
exclusion_threshold <- median(ChocsEtCO2_Base0[["CO2"]]) + 1.5 * IQR(ChocsEtCO2_Base0[["CO2"]])

# Récupération des "bonnes" valeurs de la variable "CO2" que nous stockons dans "abCO2"
abCO2 <- ChocsEtCO2_Base0[["CO2"]][ChocsEtCO2_Base0[["CO2"]] <= exclusion_threshold]

# On récupère la colonne "CO2" de  ChocsEtCO2_Base
CO2 <- ChocsEtCO2_Base0[["CO2"]]


Commençons quelques essais
1/ Créons une copie de "ChocsEtCO2_Base0" sous le nom que nous utiliserons par la suite, à savoir "ChocsEtCO2_Base"

Code : Tout sélectionner

ChocsEtCO2_Base <- ChocsEtCO2_Base0


2/ Corrigeons votre fonction en enlevant les lignes "inutiles" et en conservant l'essence de votre fonction

Code : Tout sélectionner

interpr_0 <- function(n, p) {
  res1 <- dplyr::filter(.data = ChocsEtCO2_Base, n %in% p)
  res2 <- dplyr::group_by(.data = res1, Pays)
  res3 <- dplyr::summarise(res2, mean(n), min(n), max(n))
  return(res3)
}


3/ Premier essai (résultats peu concluant)

Code : Tout sélectionner

interpr_0(CO2, abCO2)
#> # A tibble: 26 x 4
#>    Pays  `mean(n)` `min(n)` `max(n)`
#>    <chr>     <dbl>    <dbl>    <dbl>
#>  1 A        0.0158    -2.82     3.06
#>  2 B        0.0158    -2.82     3.06
#>  3 C        0.0158    -2.82     3.06
#>  4 D        0.0158    -2.82     3.06
#>  5 E        0.0158    -2.82     3.06
#>  6 F        0.0158    -2.82     3.06
#>  7 G        0.0158    -2.82     3.06
#>  8 H        0.0158    -2.82     3.06
#>  9 I        0.0158    -2.82     3.06
#> 10 J        0.0158    -2.82     3.06
#> # … with 16 more rows


4/ Modifions notre jeu de donnée

Code : Tout sélectionner

ChocsEtCO2_Base <- filter(ChocsEtCO2_Base, Pays=="A")


5/ Second essai, avec toujours la même ligne de commande (encore moins concluant)

Code : Tout sélectionner

interpr_0(CO2, abCO2)
#> Error in filter_impl(.data, quo): Result must have length 10, not 260


6/ Modifions de nouveau le jeu de donnée, en remplaçant toutes les valeurs de la colonne "CO2" par 1 (en théorie la moyenne devrait faire 1, non ?)

Code : Tout sélectionner

ChocsEtCO2_Base <- ChocsEtCO2_Base0
ChocsEtCO2_Base[["CO2"]] <- 1
ChocsEtCO2_Base
#> # A tibble: 260 x 2
#>    Pays    CO2
#>    <chr> <dbl>
#>  1 A         1
#>  2 A         1
#>  3 A         1
#>  4 A         1
#>  5 A         1
#>  6 A         1
#>  7 A         1
#>  8 A         1
#>  9 A         1
#> 10 A         1
#> # … with 250 more rows


7/ Troisième essai, encore une fois avec la même ligne de code (ou quand la moyenne de 1 ne fait pas 1...)

Code : Tout sélectionner

interpr_0(CO2, abCO2)
#> # A tibble: 26 x 4
#>    Pays  `mean(n)` `min(n)` `max(n)`
#>    <chr>     <dbl>    <dbl>    <dbl>
#>  1 A        0.0158    -2.82     3.06
#>  2 B        0.0158    -2.82     3.06
#>  3 C        0.0158    -2.82     3.06
#>  4 D        0.0158    -2.82     3.06
#>  5 E        0.0158    -2.82     3.06
#>  6 F        0.0158    -2.82     3.06
#>  7 G        0.0158    -2.82     3.06
#>  8 H        0.0158    -2.82     3.06
#>  9 I        0.0158    -2.82     3.06
#> 10 J        0.0158    -2.82     3.06
#> # … with 16 more rows


Je pense qu'ici on voit très clairement que ce n'est pas du tout bon.
On utilise trois fois la même ligne "interpr_0(CO2, abCO2)" et on obtient à chaque fois des résultats "faux".

Maintenant, corrigeons véritablement la fonction, en ajoutant un argument "data" et en imposant à "n" d'être le nom de la colonne (que l'on récupérera via "get()")
1/ On reprend notre faux jeux de donnée

Code : Tout sélectionner

library(tidyverse)
set.seed(08032019)
ChocsEtCO2_Base0 <- dplyr::tibble(
  Pays = rep(LETTERS, each = 10),
  CO2 = rnorm(length(Pays))
)
ChocsEtCO2_Base0
#> # A tibble: 260 x 2
#>    Pays      CO2
#>    <chr>   <dbl>
#>  1 A      1.05 
#>  2 A      0.888
#>  3 A     -0.460
#>  4 A     -0.217
#>  5 A     -0.961
#>  6 A     -0.0877
#>  7 A      0.593
#>  8 A      1.02 
#>  9 A     -0.0509
#> 10 A     -1.92 
#> # … with 250 more rows

# Création d'un seuil pour exclure/inclure que certaines valeurs
exclusion_threshold <- median(ChocsEtCO2_Base0[["CO2"]]) + 1.5 * IQR(ChocsEtCO2_Base0[["CO2"]])

# Récupération des "bonnes" valeurs de la variable "CO2" que nous stockons dans "abCO2"
abCO2 <- ChocsEtCO2_Base0[["CO2"]][ChocsEtCO2_Base0[["CO2"]] <= exclusion_threshold]

# On récupère la colonne "CO2" de  ChocsEtCO2_Base
CO2 <- ChocsEtCO2_Base0[["CO2"]]


2/ Correction de la fonction

Code : Tout sélectionner

interpr_1 <- function(n, p, data) {
  res1 <- dplyr::filter(.data = data, get(n) %in% p)
  res2 <- dplyr::group_by(.data = res1, Pays)
  res3 <- dplyr::summarise(res2, mean(get(n)), min(get(n)), max(get(n)))
  return(res3)
}


3/ Quatrième essai et c'est beaucoup mieux, non ?

Code : Tout sélectionner

interpr_1(n = "CO2", p = abCO2, data = ChocsEtCO2_Base0)
#> # A tibble: 26 x 4
#>    Pays  `mean(get(n))` `min(get(n))` `max(get(n))`
#>    <chr>          <dbl>         <dbl>         <dbl>
#>  1 A            -0.0149        -1.92          1.05
#>  2 B            -0.0133        -1.41          1.15
#>  3 C             0.0186        -2.82          1.24
#>  4 D            -0.293         -1.30          1.37
#>  5 E            -0.359         -1.68          0.724
#>  6 F            -0.408         -1.18          0.353
#>  7 G             0.643         -0.286         1.34
#>  8 H             0.0490        -1.64          1.79
#>  9 I             0.115         -2.05          1.36
#> 10 J            -0.0707        -1.18          0.746
#> # … with 16 more rows


En bonus, une petite variante de la fonction:

Code : Tout sélectionner

interpr_2 <- function(n, p, data) {
  data %>%
    dplyr::filter(get(n) %in% p) %>%
    dplyr::group_by(Pays) %>%
    dplyr::summarise_at(.vars = vars(!!n), .funs = funs(mean, min, max))
}
interpr_2(n = "CO2", p = abCO2, data = ChocsEtCO2_Base0)
#> # A tibble: 26 x 4
#>    Pays     mean    min   max
#>    <chr>   <dbl>  <dbl> <dbl>
#>  1 A     -0.0149 -1.92  1.05
#>  2 B     -0.0133 -1.41  1.15
#>  3 C      0.0186 -2.82  1.24
#>  4 D     -0.293  -1.30  1.37
#>  5 E     -0.359  -1.68  0.724
#>  6 F     -0.408  -1.18  0.353
#>  7 G      0.643  -0.286 1.34
#>  8 H      0.0490 -1.64  1.79
#>  9 I      0.115  -2.05  1.36
#> 10 J     -0.0707 -1.18  0.746
#> # … with 16 more rows



Edit avec votre dernier message:

Code : Tout sélectionner

aberr <- function(data = base1, col1){
  bcol1 <- boxplot(data$col1, col = "grey", main = "Osef")
  abcol1 <- bcol1$out
  # truc1 <- unique(filter(data, get(col1) %in% abcol1)$Pays) # ligne inutile ? du moins dans le cas présent
  summarise(
    .data = group_by(.data = filter(data, col1 %in% abcol1), Pays),
    mean(get(col1)),
    min(get(col1)),
    max(get(col1))
  )
}

ou

Code : Tout sélectionner

aberr <- function(data = base1, col1){
  bcol1 <- boxplot(data$col1, col = "grey", main = "Osef")
  abcol1 <- bcol1$out
  # truc1 <- unique(filter(data, get(col1) %in% abcol1)$Pays) # ligne inutile ? du moins dans le cas présent
 
  data %>%
    filter(get(col1) %in% abcol1) %>%
    group_by(Pays) %>%
    summarise(
      mean(get(col1)),
      min(get(col1)),
      max(get(col1))
    )
}


Petites recommandations de lecture:
https://r4ds.had.co.nz/
https://style.tidyverse.org/index.html

Cordialement,
Mickaël
mickael.canouil.fr | rlille.fr

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Renvoyer un élément d'une colonne correspondant à la ligne d'un autre élément

Messagepar Logez Maxime » 08 Mar 2019, 15:32

re,

un truc pas mal pour voir ce qui se passe en interne d'une fonction c'est de faire :

Code : Tout sélectionner

aberr <- function(data.frame=base1,col1){
  bcol1 <- boxplot(base1$col1,col="grey",main="Osef")
  abcol1 <- bcol1$out
  truc1 <- unique(filter(base1, col1 %in% abcol1)$Pays)
  truc2 <- summarise(group_by(filter(base1, col1 %in% abcol1), Pays), mean(col1), min(col1), max(col1))
  return(truc2)
}

# on debug la fonction
debug(aberr)
# on la lance et on regarde pas à pas ce qui se passe :
aberr(iris, "Sepal.Length")
debugging in: aberr(iris, "Sepal.Length")
debug à #1 :{
    bcol1 <- boxplot(base1$col1, col = "grey", main = "Osef")
    abcol1 <- bcol1$out
    truc1 <- unique(filter(base1, col1 %in% abcol1)$Pays)
    truc2 <- summarise(group_by(filter(base1, col1 %in% abcol1),
        Pays), mean(col1), min(col1), max(col1))
    return(truc2)
}
Browse[2]> # ici on tape juste entrée pour passer à la suite
debug à #2 :bcol1 <- boxplot(base1$col1, col = "grey", main = "Osef")
Browse[2]> base1 # pour voir si base1 existe
Erreur : objet 'base1' introuvable
Browse[2]> col1 # pour voir ce qu'il y a dans col1
[1] "Sepal.Length"
Browse[2]>
Error in boxplot(base1$col1, col = "grey", main = "Osef") :
  objet 'base1' introuvable
undebug(aberr)
Il y a plusieurs choses. Déjà dans cette fonction comme tu n'as pas d'argument qui s'appelle base1 il ne trouvera pas de base1 par la suite.
Ensuite quand tu tapes base1$col1 dans le corps de ta fonction, col1 ne va pas être remplacé par le nom de ta colonne que tu lui aura donné. Il va chercher la colonne qui s'appelle 'col1' dans base1. Comme il n'y a pas de colonne "col1" dans base1 il ne peut pas trouver les données et donc il ne peut pas faire le boxplot d'où le message d'erreur d'avant. Par contre si tu fais base1[, col1] alors la col1 va correspondre à l'objet col1 et il va se servir de la valeur contenu dans cet objet. Pour être plus clair :

Code : Tout sélectionner

aberr <- function(base1, col1) {
  base1[, col1]
  }
aberr(iris, "Sepal.Length")
Si tu fais ça comme ça alors dans ta fonction col1 est un vecteur de caractère qui ne contient que la valeur "Sepal.Length". Du coup faire base1[, col1] c'est comme faire base1[, "Sepal.Length"] ce qui n'est pas le cas quand tu utilises le '$', quand tu fais base1$col1.
J'espère que cette partie là au moins sera plus claire.

Maxime


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Google [Bot] et 1 invité