2017-08-14 1 views
0

J'ai très grand data.table que je veux réduire la voilure de cette façon:tri conditionnel dans le tableau de données

  1. Un seul identifiant unique
  2. S'il y a d'autres données que « X » dans le même journal , cet autre devrait rester
  3. Si seulement X, le premier X doit rester
  4. S'il y a plus d'un autre que « X », tous ceux-ci devraient rester, séparés par des virgules, mais pas le « X ».

ensemble de données de l'échantillon:

library(data.table) 
dt <- data.table(
    id=c(1,1,2,3,3,4,4,4,5,5), 
    log=c(11,11,11,12,12,12,12,12,13,13), 
    art=c("X", "Y", "X", "X", "X", "Z", "X", "Y","X", "X") 
) 
dt 
id log art 
1: 1 11 X 
2: 1 11 Y 
3: 2 11 X 
4: 3 12 X 
5: 3 12 X 
6: 4 12 Z 
7: 4 12 X 
8: 4 12 Y 
9: 5 13 X 
10: 5 13 X 

sortie requis:

id log art  
    1  11 Y  
    2  11 Y 
    3  12 Z,Y 
    4  12 Z,Y 
    5  13 X 
+1

id = 3 et log = 12 ne contient pas '' Z' ou Y', Pourtant, il est dans votre sortie attendue. Aussi pourriez-vous s'il vous plaît formater votre code? – mtoto

+0

Eh bien, peut-être que ce n'était pas tout à fait clair - s'il n'y a qu'un Y dans le journal 12, tous les journaux 12 devraient être Y. –

Répondre

2

Voici une méthode, bien qu'il y ait peut-être une approche plus efficace.

unique(dt[,.(id, log)])[dt[, .(art=if(.N == 1 | all(art == "X")) 
             art[1] else toString(unique(art[art != "X"]))), 
          by=log], on="log"] 

qui retourne

id log art 
1: 1 11 Y 
2: 2 11 Y 
3: 3 12 Z, Y 
4: 4 12 Z, Y 
5: 5 13 X 

effectuer une jointure gauche des valeurs de consigne d'art par chaque connecter sur les paires uniques d'identification et log. Cela suppose qu'aucun ID ne couvre deux journaux, ce qui est le cas dans l'exemple.

+0

Désolé, mais je ne me suis pas fait clair. Tout en art dans chaque niveau de notation devrait être le même. –

+1

@JeppeOlsen Ah. Je vois ce que tu veux dire. J'ai ajusté le code pour produire le résultat que vous mentionnez. – lmo

+0

Merci. Cela fait le travail :) –

1

Nous pouvons essayer

dt[, .(art = if(all(art=="X")) "X" else 
    toString(unique(art[art != "X"]))), .(id, logbld = log)] 
# id logbld art 
#1: 1  11 Y 
#2: 2  11 X 
#3: 3  12 X 
#4: 4  12 Z, Y 
#5: 5  13 X 
0

Je voulais juste essayer avec dplyr:

library(data.table) 
library(dplyr) 
    dat <- setDT(dt %>% group_by(id) %>% 
         unique() %>% 
         summarise(bldlog = mean(log), 
           art = gsub("X,|,X", "",paste(art, collapse = ",")))) 


dat 

# id bldlog art 
# 1: 1  11 Y 
# 2: 2  11 X 
# 3: 3  12 X 
# 4: 4  12 Z,Y 
# 5: 5  13 X 
+0

Je ne pense pas que 'setDT' est conçu pour être agréable avec tibbledy-dos, sauf si hadley a implémenté une méthode setDT.tibbledy quelque part. Pour la sécurité/la santé mentale, j'utiliserais 'data.table()' ou 'as.data.table()'. – Frank

+0

@Frank Correct, il n'est pas conçu pour eux. Mais avez-vous déjà eu un problème avec l'utilisation de 'setDT' sur un' tibble'? – Masoud

+1

Je ne le ferais jamais, mais peut-être que je suis trop prudent. Btw, si vous chargez dtplyr, je suppose que 'tbl_dt' et' data.table' seront déjà dans le vecteur 'class', donc pas besoin de' setDT' – Frank