[resolu]ajouter une colonne dans une liste

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

Golfesh Alphonse
Messages : 138
Enregistré le : 30 Aoû 2012, 08:57

[resolu]ajouter une colonne dans une liste

Messagepar Golfesh Alphonse » 24 Avr 2015, 14:12

bonjour,

je voudrais faire quelque chose comme ça:

Code : Tout sélectionner

res2[[ff]][nbi,] = cbind(res2[[ff]][nbi,],2)


res2 est une liste. Je voudrais ajouter au tableau que je lis en res2[[ff]][nbi,] une colonne avec la valeur 2 dans la cellule. Comment faire?

Je ne parviens pas non plus à donner un nom à cette nouvelle colonne.

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

Messagepar Mickael Canouil » 24 Avr 2015, 14:16

Quelque chose comme cela devrait fonctionner

Code : Tout sélectionner

newres2 <- lapply(res2, function (tab) {
    tmp <- cbind(tab, lenom = NA)
    tmp[nbi, "lenom"] <- 2
    return(tmp)
})
Mickaël
mickael.canouil.fr | rlille.fr

Gabriel Terraz
Messages : 591
Enregistré le : 26 Sep 2011, 15:11

Messagepar Gabriel Terraz » 24 Avr 2015, 14:19

Salut,
Je ne comprend pas ton nbi : tu fais une sélection sur les lignes dans ton tableau ?
Dans ce cas la c'est pour remplacer certaines valeurs et non pas rajouter une colonne ?

Je suis à coté de la plaque ?

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

Messagepar Mickael Canouil » 24 Avr 2015, 14:22

J'ai modifié mon post précédent.

A priori, il s'agit d'avoir une colonne supplémentaire pour tout les tableaux de res2.
Et pour les indices "nbi" de ces tableaux, mettre la valeur 2 dans la colonne supplémentaire.

Enfin, c'est comme ça que j'ai interprété l'énoncé...
Mickaël
mickael.canouil.fr | rlille.fr

Golfesh Alphonse
Messages : 138
Enregistré le : 30 Aoû 2012, 08:57

Messagepar Golfesh Alphonse » 24 Avr 2015, 16:57

Il me semble que vous avez bien compris.

J'ai une liste au sein de laquelle je veux rajouter une colonne sur tout les elements.
Ce sont des tableaux (pas au sens du type tableau, seulement le visuel). Les intitulés de colonne sont toujours les meme. Pour acceder aux tableaux jusque là j'utilisais

Code : Tout sélectionner

res2[[ff]]


Puis au sein de chaque tableau, j'ai un nombre de ligne différent. Et c'est là tout mon problème. Donc j'ai trouver que pour acceder a chacune des ligne il me faut rajouter [nbi,] (nbi est le numero de la ligne) pour obtenir la ligne voulu.

Pour simplifier, on va dire que j'ai 3 colonne dans tout mes tableaux. et je voudrais en rajouter une 4eme partout, mais avec une velaur diffrente dans chaque ligne de la colonne rajouté.

Exemple
Res2[[1]] vaut:
......col1 col2 col3
nbi1..e....T.......R


et j'ai la valeur 5 a rajouter. J'ai pris le parti de présenter le résultat comme ça:
......col1 col2 col3 col4
nbi1..e....T.......R....5


et je vous demande comment coder l'opération.

Enfin, je crois que Mickaël a repondu. Je vous tiens au courant dès que possible, merci beaucoup!

Gabriel Terraz
Messages : 591
Enregistré le : 26 Sep 2011, 15:11

Messagepar Gabriel Terraz » 25 Avr 2015, 08:41

Salut,
Pour t'aider à faire quelque chose d'efficace, il faudrait savoir combien de modalités différentes tu as en plus de "nbi ==2".

Gabriel

Golfesh Alphonse
Messages : 138
Enregistré le : 30 Aoû 2012, 08:57

Messagepar Golfesh Alphonse » 25 Avr 2015, 19:11

C'est assez aléatoire. généralement j'aurai nbi sera compris entre 1 et environ 30. Dans quelques cas, nbi va peut être atteindre 3 à 4000. ça va coincer à ce moment là?
res2 en revanche depassera pas 24 de long

Malheureusement, je ne parviens pas a intégrer le bout de code de Mickaël.

Voici ce que je voulais faire et qui ne marche pas:

Code : Tout sélectionner

for (ff in 1:length(res2))
{
   for (nbi in  1:nrow(res2[[ff]]))
   {
      numCol = which(names(res2[ff])==res2[[ff]][nbi,1:19])
      if (length(numCol)==0){ res2[[ff]][nbi,] = list(cbind(res2[[ff]][nbi,],0))}else{
      if (numCol == 17){ res2[[ff]][nbi,] = list(cbind(res2[[ff]][nbi,],1))}
      if (numCol == 18){ res2[[ff]][nbi,] = list(cbind(res2[[ff]][nbi,],2))}
      if (numCol == 19){ res2[[ff]][nbi,] = list(cbind(res2[[ff]][nbi,],3))}
      }
   }
}


A la place de mettre toujours 2, je fait un test sur la ligne. Si j'ai pas de resulat je met 0, sinon 1 2 ou 3 selon le resultat

j'essaye ça:

Code : Tout sélectionner

lapply(res2[ff],function (tab) {
      name = names(tab)
      lapply(tab[[1]],function (x) {
         apply(as.matrix(x)[,1:19],1,function (tabfinal){
         numCol = which(name== tabfinal)
         tmp <- cbind(tab, lenom = NA)
         if (length(numCol)==0){val=0}else{if (numCol == 17){val=1}
         if (numCol == 18){val=2}
         if (numCol == 19){val=3}
         }
         tmp[tabfinal, "lenom"] <- val
         return(tmp)
         })      
      })
   })

et r me repond:
Error in as.matrix(x)[, 1:19] : subscript out of bounds

Mais bon, j'ai bien l'impression de faire fausse route. Comment faire plus simple? La raison d'etre de cette imbrication de apply est de récupérer le nom de chaque res2[ff] pour l'utiliser ensuite. Sauf que je ne sais pas passer 2 arguments à un apply et que la fonction la plus imbriquée devrait pas voir ce nom recupéré en dehors d'elle.

Gabriel Terraz
Messages : 591
Enregistré le : 26 Sep 2011, 15:11

Messagepar Gabriel Terraz » 26 Avr 2015, 09:39

Salut,
En fait je crois que je ne comprend rien à ce que tu veux faire... !
Un exemple reproductible pourrait aider je pense.

Golfesh Alphonse
Messages : 138
Enregistré le : 30 Aoû 2012, 08:57

Messagepar Golfesh Alphonse » 26 Avr 2015, 20:02

ça m'étonne pas, mon dernier code doit être vraiment faux!
Voici ce qui génère ma liste multi étage. je n'ai pas réussi à la recréer autrement.

Code : Tout sélectionner

n = c("youpi", "rrr", "iiii", "poiu","qsdf")
s = c("aa", "bb", "cc", "dd","ko")
c = c("aze", "sdtgf", "cxb", "vbnv","cc")
f = c("tgn", "bbz", "cac", "ded","nnn")
tab1 = data.frame(n, s,c , f)
colnames(tab1)=   c("un","deux","trois","quatre" )

a = c("ooo", "dd", "omlp", "erty")
e = c("sd", "ds", "cc", "vv")

tab2 = data.frame(e,a)
colnames(tab2)=   c("FR","ES" )

res <- sapply(as.character(unlist(tab2)), function(x) which(tab1==x, arr.ind=T))
res <- res[sapply(res, nrow)>0.5]
res2 <- lapply(res, function(x) tab1[x[,1],1:2])
res2


on obtient:
$cc
un deux
iiii cc
qsdf ko

$dd
un deux
poiu dd


Je voudrais faire un code pour obtenir:
$cc
un deux trois
iiii cc 2
qsdf ko 0

$dd
un deux trois
poiu dd 2


Les chiffres changeront selon la condition:
Si le nom de la liste (ici $cc ou $dd) apparait dans la liste, on note le numero de colonne dans la nouvelle colonne intitulée 3. Si le nom de la liste n'apparait pas on note 0.

Gabriel Terraz
Messages : 591
Enregistré le : 26 Sep 2011, 15:11

Messagepar Gabriel Terraz » 27 Avr 2015, 08:07

Effectivement, je n'avais rien compris !

Voici une fonction bien moche qui a l'air de fonctionner :

Code : Tout sélectionner

tes <- sapply(names(res2) , function(x) res2[[x]]==x)
test2 <- slapply(test , function(x) apply(x , 1 , function(i) ifelse(sum(i) > 0 , (1:length(i))[i] , 0)))
lapply(names(res2) , function(x) data.frame(res2[[x]] , trois = test2[[x]]))

Nicolas Péru
Messages : 1408
Enregistré le : 07 Aoû 2006, 08:13

Messagepar Nicolas Péru » 27 Avr 2015, 09:22

Dans le même ordre d'idée :

Code : Tout sélectionner

mapply(function(x){
tab <-res2[[x]]
a <- apply(tab,1,function(z) ifelse(any(z==x),which(z==x),0))
cbind(tab,trois=a)
}
,names(res2),SIMPLIFY =FALSE)


il y a juste pour le nom de la colonne à ajouter où ça manque d'automatisme mais sans en connaître plus sur ce que tu veux sur ce point j'ai pris une solution pragmatique.

Nicolas

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

Messagepar Logez Maxime » 27 Avr 2015, 11:15

Bonjour,

une solution possible avec la librairie dplyr :

Code : Tout sélectionner

f <- function (x)
x %in% c("cc", "dd")

lapply(res2, function(x) cbind(x,trois=colSums(t(x%>% mutate_each(funs(f)))*(1:2))))

# ou sans la librairie
lapply(res2, function(x) cbind(x, trois=colSums(apply(x, 1, f)*(1:2))))
Cordialement,
Maxime

Golfesh Alphonse
Messages : 138
Enregistré le : 30 Aoû 2012, 08:57

Messagepar Golfesh Alphonse » 28 Avr 2015, 07:22

Merci à tout les 3! Vos solutions sont excellentes.
Je vais utiliser celle de nicolas, que je comprends facilement.

Maxime, j'ai du mal avec:

Code : Tout sélectionner

f <- function (x)
apply(x, 1, f)*(1:2)


Gabriel, je ne comprends pas::

Code : Tout sélectionner

ifelse(sum(i) > 0 , (1:length(i))[i] , 0)


Retourner vers « Questions en cours »

Qui est en ligne

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