2010-08-30 22 views
1

J'ai déjà remarqué à quelques reprises que travailler avec dates ne permet pas d'utiliser les astuces habituelles de R. Dites que j'ai une dataframe Data with Dates (voir ci-dessous), et je veux convertir la dataframe complète en une classe date . La seule solution que je pouvais venir avec jusqu'à maintenant:Comment transformer une dataframe de caractères en dates respectives?

for (i in 1:ncol(Data)){ 
    Data[,i] <- as.Date(Data[,i],format="%d %B %Y") 
} 

Cela donne une trame de données avec la structure correcte:

> str(Data) 
'data.frame': 6 obs. of 4 variables: 
$ Rep1:Class 'Date' num [1:6] 12898 12898 13907 13907 13907 ... 
$ Rep2:Class 'Date' num [1:6] 13278 13278 14217 14217 14217 ... 
$ Rep3:Class 'Date' num [1:6] 13600 13600 14340 14340 14340 ... 
$ Rep4:Class 'Date' num [1:6] 13831 13831 14669 14669 14669 ... 

En utilisant une approche classique appliquer donne quelque chose de complètement différent. Bien que toutes les variables sont de la même classe et vont à la même classe, je ne peux pas obtenir un cadre ou d'une matrice de données de la classe correcte en sortie:

> str(sapply(Data,as.Date,format="%d %B %Y")) 
num [1:6, 1:4] 12898 12898 13907 13907 13907 ... 
- attr(*, "dimnames")=List of 2 
    ..$ : NULL 
    ..$ : chr [1:4] "Rep1" "Rep2" "Rep3" "Rep4" 
> str(apply(Data,2,as.Date,format="%d %B %Y")) 
num [1:6, 1:4] 12898 12898 13907 13907 13907 ... 
- attr(*, "dimnames")=List of 2 
    ..$ : NULL 
    ..$ : chr [1:4] "Rep1" "Rep2" "Rep3" "Rep4" 

Si vous voulez transformer ces matrices à nouveau Date objets, vous avez besoin d'une origine. Cette origine peut différer d'un système à l'autre, donc utiliser as.Date ou une autre fonction après apply() n'aide pas beaucoup non plus. Si vous appliquez l'origine, vous obtenez à nouveau un vecteur.

Quelqu'un est-il une solution propre pour ce type de données? Ci-dessous l'image que j'ai utilisée dans les exemples.

Data <- structure(list(Rep1 = c(" 25 April 2005 ", " 25 April 2005 ", 
" 29 January 2008 ", " 29 January 2008 ", " 29 January 2008 ", 
" 29 January 2008 "), Rep2 = c(" 10 May 2006 ", " 10 May 2006 ", 
" 4 December 2008 ", " 4 December 2008 ", " 4 December 2008 ", 
" 4 December 2008 "), Rep3 = c(" 28 March 2007 ", " 28 March 2007 ", 
" 6 April 2009 ", " 6 April 2009 ", " 6 April 2009 ", " 6 April 2009 " 
), Rep4 = c(" 14 November 2007 ", " 14 November 2007 ", " 1 March 2010 ", 
" 1 March 2010 ", " 1 March 2010 ", " 1 March 2010 ")), .Names = c("Rep1", 
"Rep2", "Rep3", "Rep4"), row.names = c("1", "2", "3", "4", "5", 
"6"), class = "data.frame") 

Répondre

2

Que diriez-vous

str(as.data.frame(lapply(Data,as.Date,format="%d %B %Y"))) 
# 'data.frame': 6 obs. of 4 variables: 
# $ Rep1:Class 'Date' num [1:6] 12898 12898 13907 13907 13907 ... 
# $ Rep2:Class 'Date' num [1:6] 13278 13278 14217 14217 14217 ... 
# $ Rep3:Class 'Date' num [1:6] 13600 13600 14340 14340 14340 ... 
# $ Rep4:Class 'Date' num [1:6] 13831 13831 14669 14669 14669 ... 
+0

Darn, comment pourrais-je négliger celui-là. THX! –

+0

'apply' est tellement ennuyeux avec ces conversions dans les coulisses, voir par ex. [comment il pourrait jouer avec des facteurs] (http://stackoverflow.com/questions/2392216/why-is-as-factor-returns-a-character-when-used-inside-apply/2392343) – Marek

+0

Juste pour l'exhaustivité: Si vous voulez une matrice comme résultat, Marek a proposé cette solution dans un autre thread: Out <- as.Date (Données, format = "% d% B% Y"); dim (Out) <- dim (Data). –

4

Je pense que la manière la plus succincte pour ce faire est:

Data[] <- lapply(Data, as.Date,format="%d %B %Y") 

Cela aussi généralise bien au cas où toutes les colonnes sont des dates:

Data[date_col] <- lapply(Data[date_col], as.Date,format="%d %B %Y") 

Vous pouvez aussi s implify l'analyse syntaxique de la date avec deux autres paquets

library(stringr) 
library(lubridate) 
Data[] <- lapply(Data, function(x) dmy(str_trim(x))) 

qui est un peu plus bavard, mais il a l'avantage que vous n'avez pas besoin de comprendre le format de données vous.

+0

J'utilise souvent ceci pour enlever quelques colonnes de 'data.frame' à la fois:' Data [date_col] <- list (NULL) ' – Marek