Spécifiez le format de date personnalisé pour l'argument colClasses dans read.table / read.csv


101

Question:

Existe-t-il un moyen de spécifier le format de date lors de l'utilisation de l'argument colClasses dans read.table / read.csv?

(Je me rends compte que je peux convertir après l'importation, mais avec de nombreuses colonnes de date comme celle-ci, ce serait plus facile de le faire à l'étape d'importation)


Exemple:

J'ai un .csv avec des colonnes de date au format %d/%m/%Y.

dataImport <- read.csv("data.csv", colClasses = c("factor","factor","Date"))

Cela entraîne une erreur de conversion. Par exemple, 15/07/2008devient 0015-07-20.


Code reproductible:

data <- 
structure(list(func_loc = structure(c(1L, 2L, 3L, 3L, 3L, 3L, 
3L, 4L, 4L, 5L), .Label = c("3076WAG0003", "3076WAG0004", "3076WAG0007", 
"3076WAG0009", "3076WAG0010"), class = "factor"), order_type = structure(c(3L, 
3L, 1L, 1L, 1L, 1L, 2L, 2L, 3L, 1L), .Label = c("PM01", "PM02", 
"PM03"), class = "factor"), actual_finish = structure(c(4L, 6L, 
1L, 2L, 3L, 7L, 1L, 8L, 1L, 5L), .Label = c("", "11/03/2008", 
"14/08/2008", "15/07/2008", "17/03/2008", "19/01/2009", "22/09/2008", 
"6/09/2007"), class = "factor")), .Names = c("func_loc", "order_type", 
"actual_finish"), row.names = c(NA, 10L), class = "data.frame")


write.csv(data,"data.csv", row.names = F)                                                        

dataImport <- read.csv("data.csv")
str(dataImport)
dataImport

dataImport <- read.csv("data.csv", colClasses = c("factor","factor","Date"))
str(dataImport)
dataImport

Et voici à quoi ressemble la sortie:

sortie de code


Une manière piratée de faire cela serait de créer votre propre version de read.tableet d'ajouter un formatargument qui est transmis à as.Date. Je ne serais pas surpris s'il existe une meilleure façon de ne pas penser.
joran

Réponses:


158

Vous pouvez écrire votre propre fonction qui accepte une chaîne et la convertit en date en utilisant le format souhaité, puis utilisez le setAspour la définir comme asméthode. Ensuite, vous pouvez utiliser votre fonction dans le cadre des colClasses.

Essayer:

setAs("character","myDate", function(from) as.Date(from, format="%d/%m/%Y") )

tmp <- c("1, 15/08/2008", "2, 23/05/2010")
con <- textConnection(tmp)

tmp2 <- read.csv(con, colClasses=c('numeric','myDate'), header=FALSE)
str(tmp2)

Puis modifiez si nécessaire pour travailler pour vos données.

Éditer ---

Vous voudrez peut-être exécuter d' setClass('myDate')abord pour éviter l'avertissement (vous pouvez ignorer l'avertissement, mais cela peut devenir ennuyeux si vous le faites beaucoup et c'est un simple appel qui vous en débarrasse).


2
Wow - setAs est une bouée de sauvetage! Comment n'ai-je jamais vu cette fonction auparavant?
user295691

4
Notez que vous pourriez obtenir un avertissement «pas de définition pour la classe« myDate »» comme détaillé dans cette question .
Danny D'Amours

1
Que setMethod('myDate')doit-on faire? L'exécuter me donne juste une erreur ...
Josh O'Brien

1
@ JoshO'Brien, désolé que cela aurait dû être setClass(corrigé maintenant). Ce qu'il fait est d'empêcher setAsd'émettre un avertissement concernant «myDate» qui n'existe pas en tant que classe. L'avertissement est inoffensif et tout fonctionne toujours, mais la définition de la classe signifie que vous ne voyez même pas l'avertissement.
Greg Snow

1
@MySchizoBuddy, Si vous n'avez qu'une seule colonne de date et que vous le faites une fois, la manière dont vous le faites n'a probablement pas d'importance. Mais si vous avez plusieurs colonnes dans votre ensemble de données qui sont des dates, je pense que cette approche serait probablement plus simple que de changer chacune des colonnes après la lecture.
Greg Snow

25

S'il n'y a qu'un seul format de date que vous souhaitez modifier, vous pouvez utiliser le Defaultspackage pour modifier le format par défaut dansas.Date.character

library(Defaults)
setDefaults('as.Date.character', format = '%d/%M/%Y')
dataImport <- read.csv("data.csv", colClasses = c("factor","factor","Date"))
str(dataImport)
## 'data.frame':    10 obs. of  3 variables:
##  $ func_loc     : Factor w/ 5 levels "3076WAG0003",..: 1 2 3 3 3 3 3 4 4 5
##  $ order_type   : Factor w/ 3 levels "PM01","PM02",..: 3 3 1 1 1 1 2 2 3 1
##  $ actual_finish: Date, format: "2008-10-15" "2009-10-19" NA "2008-10-11" ...

Je pense que la réponse de @Greg Snow est bien meilleure, car elle ne change pas le comportement par défaut d'une fonction souvent utilisée.


7

Au cas où vous auriez besoin de temps aussi:

setClass('yyyymmdd-hhmmss')
setAs("character","yyyymmdd-hhmmss", function(from) as.POSIXct(from, format="%Y%m%d-%H%M%S"))
d <- read.table(colClasses="yyyymmdd-hhmmss", text="20150711-130153")
str(d)
## 'data.frame':    1 obs. of  1 variable:
## $ V1: POSIXct, format: "2015-07-11 13:01:53"

2

Il y a longtemps, le problème a été résolu par Hadley Wickham. Donc, de nos jours, la solution est réduite à un seul revêtement:

library(readr)
data <- read_csv("data.csv", 
                  col_types = cols(actual_finish = col_datetime(format = "%d/%m/%Y")))

Peut-être que nous voulons même nous débarrasser des choses inutiles:

data <- as.data.frame(data)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.