2017-10-17 5 views
0

J'ai une grande base de données. Un petit sous-ensemble est la suivante:Supprime les virgules des vecteurs de caractères basés sur des noms de colonnes spécifiques dans R

structure(list(Date = c("2017-08-12", "2017-08-12", "2017-08-12" 
), `Time (sec)` = c("19:01:04", "07:30:18", "04:29:38"), `4+DURATION` = c("26", 
    "58,000", "27"), `4+'000 (AVG)` = c("0.0000", "0.0000", "0.0000"), 
    `15+DURATION` = c("26", "57,000", "27"), `15+'000 (AVG)` = c("0.0000", 
    "0.0000", "0.0000")), .Names = c("Date", "Time (sec)", "4+DURATION", 
    "4+'000 (AVG)", "15+DURATION", "15+'000 (AVG)"), row.names = 3:5, class = "data.frame") 

La trame de données réelle ressemble à ceci:

 Date Time (sec) 4+DURATION 4+'000 (AVG) 15+DURATION 15+'000 (AVG) 
3 2017-08-12 19:01:04   26  0.0000   26  0.0000 
4 2017-08-12 07:30:18  58,000  0.0000  57,000  0.0000 
5 2017-08-12 04:29:38   27  0.0000   27  0.0000 

Dans cette colonne 3 partir le reste des colonnes ont été stockées en tant que vecteur de caractères. J'essaye de convertir le caractère en numérique. Ce qui suit est le code que j'ai utilisé.

cols.num <- names(dat[,-c(1:2)]) 
dat[cols.num] <- sapply(dat[cols.num],as.numeric) 

dat est ma trame de données. Cela force les valeurs NA dans les deux colonnes de durée où la valeur du caractère comporte une virgule supplémentaire.

J'ai essayé de l'enlever par

df[,unique(grep("DUR", names(df), value=T))] <- gsub(",","",df[,unique(grep("DUR", names(df), value=T))]) 

Mais cela crée un df comme celui-ci

Date Time (sec)   4+DURATION 4+'000 (AVG)   15+DURATION 15+'000 (AVG) 
3 2017-08-12 19:01:04 c("26" "58000" "27")  0.0000 c("26" "57000" "27")  0.0000 
4 2017-08-12 07:30:18 c("26" "57000" "27")  0.0000 c("26" "58000" "27")  0.0000 
5 2017-08-12 04:29:38 c("26" "58000" "27")  0.0000 c("26" "57000" "27")  0.0000 

Mais la sortie désirée est:

Date Time (sec) 4+DURATION 4+'000 (AVG) 15+DURATION 15+'000 (AVG) 
3 2017-08-12 19:01:04   26  0.0000   26  0.0000 
4 2017-08-12 07:30:18  58000  0.0000  57000  0.0000 
5 2017-08-12 04:29:38   27  0.0000   27  0.0000 

Le problème dans ce cadre de données est, je ne sais pas quelle colonne aura la valeur de la durée et le nom de la colonne avec la valeur de la durée ne cesse de changer, à partir de 4+ DURATION à 45 + DUREE, etc. Je veux enlever la virgule de tous les vecteurs avec DURATION dans leurs noms avant de faire le vecteur en numérique.

+2

Vous devez l'appliquer. 'gsub' n'est pas vectorisé. 'df [, unique (grep (" DUR ", noms (df), valeur = T))] - Sotos

+0

@Sotos Merci ... l'ai eu. J'essayais avec l'application .... et ai eu une série de problèmes sans fin ... Peut accepter ceci comme réponse. – Apricot

Répondre

2

Vous devez *apply pour les colonnes d'intérêt depuis gsub (Pour votre information, sub va aussi faire très bien ici) est pas vectorisée, à savoir

df[,unique(grep("DUR", names(df), value=T))] <- 
        lapply(df[,unique(grep("DUR", names(df), value=T))], function(i) 
                  as.numeric(sub(',', '', i))) 

qui donne,

 Date Time (sec) 4+DURATION 4+'000 (AVG) 15+DURATION 15+'000 (AVG) 
3 2017-08-12 19:01:04   26  0.0000   26  0.0000 
4 2017-08-12 07:30:18  58000  0.0000  57000  0.0000 
5 2017-08-12 04:29:38   27  0.0000   27  0.0000 
#str(df) 
#'data.frame': 3 obs. of 6 variables: 
# $ Date   : chr "2017-08-12" "2017-08-12" "2017-08-12" 
# $ Time (sec) : chr "19:01:04" "07:30:18" "04:29:38" 
# $ 4+DURATION : num 26 58000 27 
# $ 4+'000 (AVG) : chr "0.0000" "0.0000" "0.0000" 
# $ 15+DURATION : num 26 57000 27 
# $ 15+'000 (AVG): chr "0.0000" "0.0000" "0.0000" 
1

Une solution dplyr:

d <- structure(list(Date = c("2017-08-12", "2017-08-12", "2017-08-12" 
), `Time (sec)` = c("19:01:04", "07:30:18", "04:29:38"), `4+DURATION` = c("26", 
    "58,000", "27"), `4+'000 (AVG)` = c("0.0000", "0.0000", "0.0000"), 
    `15+DURATION` = c("26", "57,000", "27"), `15+'000 (AVG)` = c("0.0000", 
    "0.0000", "0.0000")), .Names = c("Date", "Time (sec)", "4+DURATION", 
    "4+'000 (AVG)", "15+DURATION", "15+'000 (AVG)"), row.names = 3:5, class = "data.frame") 
d2 <- d %>% mutate_at(vars(contains('DURATION')), funs(as.numeric(gsub(',', '', .)))) 
str(d2) 
+1

Vous pouvez aussi faire 'mutate_at (vars (contient ('DURATION')), ~ as.numeric (gsub (',', '',.)))' 'Avec plus les versions récentes de' dplyr' pkg – hrbrmstr

+0

Merci pour ça suggestion! –