30 votes

Gérer les dates en désordre

J'espère que vous ne pensiez pas que j'avais besoin de conseils sur les relations.

Rarement, j'ai à offrir des répondants à l'enquête la possibilité de spécifier quand un événement est survenu. Quels sont les résultats est une horrible désordre chaîne qu'honnêtement, je ne sais pas quoi faire avec. Au-delà de recoder à la main.

Ici, c'est un court exemple, des milliers:

c("May2/ 12h", "9:45 am", "11:00 AST", "avril 27 / 12:00 AST", 
"11:40 AM AST", "25 avril 2011", "12 avril 2011 / 8:44", "12 avril 2011 / 8:36", 
"Le 12 avril 2011 / 8:30", "12 avril 2011 / 8:18", "12 avril 2011 / 8:12am", 
"Le 11 avril 2011 / 5:57pm", "le 11 avril 2011 / 5:49", "le 11 avril 2011 / 5:42pm", 
"Le 11 avril 2011 / 5:36pm", "le 11 avril 2011 / 5:27", "avril 5 @ 11:26am", 
"8:50", "4 avril 12:45", "4 avril, vers 10 heures", "4 avril, vers 10 heures", 
"Mar 18, 2011 9:33am", "Mar 18, 2011 9:27", "df", "fg", "12:16", 
"9:50", "Feb 8, 2011 / 12:20pm", "8:34 am 2/4/11", "Jan 31, 2011 2:50pm", 
"Jan 31, 2011 2:45", "Jan 31, 2011 2:38pm", "Jan 31, 2011 2:26pm", 
"11h09", "11:00", "1h02 h", "10h03", "2h10", "Jan 13, 2011 9:50am Van", 
"Jan 12, 2011", "Jan 12, 2011 3:59", "Jan 12 14:19PM", 
"Jan 12, 2011 1:35", "Jan 12,2011 1:28", "1h36", "9h15", 
"9h09", "8h51", "8h45", "8h35", "1h12 h", "12h59", "11h52 suis", 
"10h45", "15h55", "31-Déc-10 11:11am", "Dec 31,10 10:15", 
"Déc 30, 2010 12:32pm", "Dec 30, 2010 12:18pm", "9:16 am", "11h16 suis", 
"11h12", "9h29 suis", "11h38", "Dec 16, 2010", "16 décembre 2010", 
"Le 16 décembre 2010", "Dec 15,2010", "14 DÉC 2010", "Dec 14 11:38", 
"Dec 14 11:35", "Dec 14 11:25", "le 13 décembre 2010", "Dec 10, 1:38 pm", 
"Dec 10, 1:26 pm", "Dec 10, 1:20 pm", "Dec 10, 1:12 pm", "9 décembre 2010", 
"11h10 suis", "10h59 suis", "10:50 am", "Mardi 7 Décembre, 9:45 Van de temps", 
"Dec 3, 2010 12:30", "Dec 3, 2010 12:20", "Dec 3, 2010 12:10 pm", 
"Le 30 novembre 2010 4.02 h", "le 30 novembre 2010", "29 novembre 120pm", 
"Novembre 29 2010 11:27", "10:12h 29 novembre 2010", "Nov 26/10 1:18", 
"10:56 am", "Nov 24", "nov 24/ 4:20 PM AST", "Nov 24/4:00 AST", 
"NOVEMBRE 24/10 2:10 pm", "novembre 24/10 11:00", "12:05 MST", 
"3.55 H", "Nov. 17/10 12:45 pm", "Nov. 16/10 12:00 noon", "Nov. 16/10 11;50 h", 
"nov 16/10 à 11 h 30", "novembre 12, 2010 @ 12:23pm", "11 novembre 2010 à 2:20", 
"Le 11 novembre 2010 à 2:15", "le 11 novembre, à 2:00", "Nov. 10/10:22am", 
"nov. 8/10...3:19 pm", "Nov 8/10 1;50 h", "novembre 8/10...12 midi", 
"Novembre 8/10..10: am", "Nov 5, 2010 1:10", "11:32 am CST", 
"Le 4 novembre à 11:10", "3 novembre 10h", "9:30", "le 11/02/2010 1:50PM", 
"Oct 29/10 2:50PM", "Oct 28 @ 11:20", "27Oct10 10:40am", "10/26/2010 11:18", 
"Oct 26/10 11h", "Oct 26/10:10: 30", "Oct 26 10:50", "10/25/2010 13:50", 
"10/22/2010 10:15", "Oct 22/10 10H", "Oct 21, 2010 3:00 pm", 
"Oct 21, 2010 2:59", "10/21/2010 11:50", "10/21/2010 11:45", 
"10/21/2010 11:40", "10/21/2010 11:30", "11:30", "Oct 20 env 1pm", 
"Oct 20/10 4:50PM", "13:48", "13:45", "Oct 20, 2010 11:45 am", 
"Le 19 octobre 3:05pm", "Oct 18,2010 2:15", "Oct 18/10 3:10PM", 
"10:30", "Oct 15/10 11:50", "oct 14 @ 11:05", "Oct 14/ 11:06", 
"4:40 13 oct atlantique", "13 oct à 4:05 pm de l'atlantique", "13 oct à 1:45 heure de l'atlantique", 
"13 Oct / 10:37", "12 OCT à 3:33", "Oct 12,2010 1:10pm", "Oct 12 / 11:45", 
Oct 12 / 9:45", "Oct 8. 2010/ 2:00", "Oct 8/10 - 1145am", "2 Sept 2010 3.52 h", 
"2 Sept 2010 10.21 suis", "1 Sept 2010 2.05 h", "1 Sept 2010", "31 Aoû 2010 - 11.52 suis", 
"31 août 10:40am", "31 aoû 2010 - 10")

En général, ces événements se produisent à proximité de la date à laquelle le répondant remplit le questionnaire, mais pas toujours. La date de l'inventaire est automatiquement enregistré et dans un format cohérent et est facile à traduire dans POSIX à l'aide de as.Date , éléments qui ne contiennent que le temps peut être ignoré et a fusionné avec la date à laquelle ils ont rempli le questionnaire.

Vos pensées sont beaucoup apprécié.

Note1: Certains d'entre vous le disent, vous devriez avoir fait X, Y, ou Z en termes de valider les réponses. Pour vous, dis - je- l'enfer oui - la prochaine fois. Je n'ai pas le concevoir! Je viens d'avoir à traiter avec elle.

Quelques faits qui peuvent aider dans une solution de contournement:

  • Le temps sera toujours des affaires heures de jour, 9am-6pm (d'où am/pm n'a pas d'importance)
  • Les années n'ont pas d'importance tant que je peux tirer à partir d'un autre champ (il sera toujours seulement être 2011/2010, qui est heureusement en dehors des délais dans toute la notation)
  • Je n'ai pas de soins sur les fuseaux horaires, comme je l'ai leur emplacement géographique

Ce que j'ai fait jusqu'à présent:

mos <- strsplit('
jan
feb
mar
apr
may
jun
jul
aug
sep
oct
nov
dec
january
february
march
april
may
june
july
august
september
october
november
december
', '\n')[[1]][-1]

days <- strsplit('
mon
tue
wed
thu
fri
sat
sun
monday
tuesday
wednesday
thursday
friday
saturday
sunday
', '\n')[[1]][-1]
## Messy Date Wrangling
x <- ## that hot ghetto mess above
# minimize
x <- tolower(x)
# remove unnecessary crap
x <- sub("2011"," ",x)
x <- sub("2010"," ",x)
x <- sub("am"," ",x)
x <- sub("pm"," ",x)
x <- sub("[p][.][m]"," ",x)
x <- sub("[a][.][m]"," ",x)
x <- sub("[.]{3}"," ",x)
x <- str_trim(x, side="both")
# divide
x <- strsplit(x,c(" "))
# conquer?

lapply(x, function(x) pmatch(x,mos))
lapply(x, function(x) pmatch(x,days))

18voto

Andrie Points 66979

Mes sympathie que votre date n'est pas aussi joli que prévu. ;-)

J'ai construit une (encore partielle) de la solution dans le sens suggéré par @Rguy.

(Veuillez noter que ce code a encore un bug: Il n'est pas toujours le bon moment. Pour une raison quelconque, il n'est pas toujours avide de match sur les chiffres avant les deux points, donc parfois de retour 1:00 lorsque le temps est 11:00.)

Tout d'abord, construire une fonction d'assistance qui s'enroule autour de gsub et grep. Cette fonction prend un caractère de vecteur de l'un de ses arguments et s'effondre en une seule chaîne de caractères séparés par des |. L'effet de cette est de vous permettre de passer facilement à de nombreux modèles à être accompagnée par une regex:

find.pattern <- function(x, pattern_list){
  pattern <- paste(pattern_list, collapse="|")
  ret <- gsub(paste("^.*(", pattern, ").*", sep=""), "\\1", x, ignore.case=TRUE)
  ret[ret==x] <- NA 
  ret2 <- grepl(paste("^(", pattern, ")$", sep=""), x, ignore.case=TRUE)
  ret[ret2] <- x[ret2] 
  ret
}

Ensuite, utilisez quelques intégré dans les noms de variables afin de construire un vecteur de mois et abréviations:

all.month <- c(month.name, month.abb)

Enfin, la construction d'un bloc de données avec les différents extraits:

ret <- data.frame(
    data = dat, 
    date1 = find.pattern(dat, "\\d+/\\d+/\\d+"),
    date2 = find.pattern(dat, 
      paste(all.month, "\\s*\\d+[(th)|,]*\\s{0,3}[(2010)|(2011)]*", collapse="|", sep="")),
    year = find.pattern(dat, c(2010, 2011)),
    month = find.pattern(dat, month.abb), #Use base R variable called month.abb for month names
    hour = find.pattern(dat, c("\\d+[\\.:h]\\d+", "12 noon")),
    ampm = find.pattern(dat, c("am", "pm"))
)

Les résultats:

head(ret, 50)
                      data  date1        date2 year month  hour ampm
20   April 4th around 10am   <NA>   April 4th  <NA>   Apr  <NA>   am
21   April 4th around 10am   <NA>   April 4th  <NA>   Apr  <NA>   am
22     Mar 18, 2011 9:33am   <NA> Mar 18, 2011 2011   Mar  9:33   am
23     Mar 18, 2011 9:27am   <NA> Mar 18, 2011 2011   Mar  9:27   am
24                      df   <NA>         <NA> <NA>  <NA>  <NA> <NA>
25                      fg   <NA>         <NA> <NA>  <NA>  <NA> <NA>
26                   12:16   <NA>         <NA> <NA>  <NA> 12:16 <NA>
27                    9:50   <NA>         <NA> <NA>  <NA>  9:50 <NA>
28   Feb 8, 2011 / 12:20pm   <NA>  Feb 8, 2011 2011   Feb  2:20   pm
29         8:34 am  2/4/11 2/4/11         <NA> <NA>  <NA>  8:34   am
30     Jan 31, 2011 2:50pm   <NA> Jan 31, 2011 2011   Jan  2:50   pm
31     Jan 31, 2011 2:45pm   <NA> Jan 31, 2011 2011   Jan  2:45   pm
32     Jan 31, 2011 2:38pm   <NA> Jan 31, 2011 2011   Jan  2:38   pm
33     Jan 31, 2011 2:26pm   <NA> Jan 31, 2011 2011   Jan  2:26   pm
34                   11h09   <NA>         <NA> <NA>  <NA> 11h09 <NA>
35                11:00 am   <NA>         <NA> <NA>  <NA>  1:00   am
36                 1h02 pm   <NA>         <NA> <NA>  <NA>  1h02   pm
37                   10h03   <NA>         <NA> <NA>  <NA> 10h03 <NA>
38                    2h10   <NA>         <NA> <NA>  <NA>  2h10 <NA>
39 Jan 13, 2011 9:50am Van   <NA> Jan 13, 2011 2011   Jan  9:50   am
40            Jan 12, 2011   <NA> Jan 12, 2011 2011   Jan  <NA> <NA>

8voto

Greg Snow Points 22040

Cela peut être l'un des rares cas où un autre outil autre que R est le meilleur à utiliser. Je sais qu'il y a certains modules Perl qui ont déjà été développées pour analyser désordonné dates, sur le module DateTime::Format::Naturel::Lang::FR peut analyser des chaînes de caractères comme: "le 1er mardi du mois de novembre dernier". Il me semble me rappeler d'un autre module qui pourrait comprendre des choses comme "le deuxième mardi suivant le premier lundi de février".

Il est également un outil au http://www.datasciencetoolkit.org/ qui saisit ce qui ressemble à des dates dans le texte et les convertit en un format standard.

6voto

Rguy Points 991

Je ne vais pas essayer d'écrire la fonction à droite maintenant, mais j'ai une idée qui pourrait fonctionner.

Recherche de chaque chaîne pour un nombre à 4 chiffres à l'appel de l'année.

Utiliser grep de recherche de chaque chaîne pour les 3 premières lettres de l'abréviation du mois. Il semble presque toutes vos données (au moins au-dessus) est un identificateur comme ça. J'avais stocker la valeur qui se trouve dans un "mois" vecteur, et mettre les blancs où aucune valeur n'est trouvée. Voici une très laid version du code (je vais le rendre plus efficace, plus tard, et ajouter le cas lorsque le mois n'est pas capitalisée!)

mos <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")   
blah <- lapply(1:12, function(i) grepl(mos[i], test))   
lapply(blah, function(i) which(i))   
months <- 0*(1:length(test))   
for (i in 1:12) {   
  months[blah[[i]]] <- i   
}  


   months
  [1]  5  0  0  4  0  4  4  4  4  4  4  4  4  4  4  4  4  0  4  4  4  3  3  0  0  0  0  2  0  1
 [31]  1  1  1  0  0  0  0  0  1  1  1  1  1  1  0  0  0  0  0  0  0  0  0  0  0 12 12 12 12  0
 [61]  0  0  0  0 12 12 12 12  0 12 12 12 12 12 12 12 12 12  0  0  0 12 12 12 12 11 11  0 11 11
 [91] 11  0 11  0 11  0 11  0  0 11 11 11  0 11  0 11 11 11  0 11 11 11 11  0 11  0  0  0 10 10
[121] 10  0 10 10 10  0  0 10 10 10  0  0  0  0  0 10 10  0  0 10 10 10 10  0 10  0 10  0  0  0
[151] 10  0 10 10 10 10 10  9  9  9  9  8  0  0 

Le jour "j" on suit le mot utilisé pour le mois immédiatement. Donc si il y a un ou 2 chiffres après le mois(qui est de caractère), extrait de ce numéro et l'appeler le jour.

Fois plus souvent avoir l' ":" ou "." le symbole, et donc de recherche de chaque chaîne de caractères. Si dans une chaîne de caractères, créer un "Temps" de vecteur avec tous les chiffres immédiatement avant et après ce personnage (en théorie, dont 2 avant et 2 après ne devrait pas causer de problème). Mettre les blancs à chaque fois que le symbole n'est pas présent. Ce serait bien si toutes les données ont été définitivement clos à la une <période de 12 heures, car alors vous n'aurez pas à vous soucier de AM et PM. Si non, Peut-être la recherche de la chaîne pour "AM" et "PM" ainsi.

Ensuite, essayez de convertir les chaînes de caractères qui ont tous les quatre ci-dessus pour POSIXct. Ceux qui ne vous convertissez pas, vous devrez entrer manuellement bien sûr. Je pense qu'il me faudrait quelques heures pour le code de la fonction décrite ci-dessus, et en fonction de la variabilité et de la taille de votre jeu de données, il peut ou peut ne pas être en vaut la peine. Aussi, il y a un risque pour les sorties incorrectes, l'ajout d'un intervalle de temps acceptable serait d'aider à l'éviter.

En résumé, il semble que vous allez avoir à coder une fonction avec tout un tas d'exceptions et puis finir à la main de codage d'une bonne partie du temps de toute façon. J'espère que quelqu'un peut fournir une meilleure solution pour vous, si.

Bonne Chance!

3voto

kohske Points 30437

Le wolfram alpha http://www.wolframalpha.com/ est certainement un excellent outil pour faire ce travail.

Au moins, elle a réussi à interpréter certains désordre de saisie de vos données. Il serait intéressant d'essayer.

Je ne sais pas si le site est adapté pour les très gros jeu de données, mais si les données n'est pas tellement grand, il sera utile.

Il n'est pas difficile d'écrire un script automatisé qui envoient des requêtes, obtenir les données et l'analyse, bien que je ne suis pas sûr si le site le permet une telle utilisation.

3voto

Iterator Points 10485

D'autres ont déjà abordé les approches standard et des paquets. Je vais prendre un point de vue différent. En utilisant des expressions régulières et fixes formats, vous obtiendrez la plupart du chemin. Pour le reste, je serais tout simplement l'aborder comme je l'aurais aucun problème dans le "pattern matching": les méthodes statistiques ou l'apprentissage de la machine. Vous avez déjà indiqué la date et l'heure des plages, et l'horodatage des bûches est aussi instructif. Par l'extraction d'un lot de fonctionnalités de texte (c'est là que les expressions régulières pourraient s'avérer utiles), vous pouvez alors essayer de carte à la fois de l'intérêt.

Il y a seulement trois choses à faire pour l'obtention de ce travail:

  1. L'extraction de caractéristiques
  2. Jeu d'apprentissage de la génération
  3. Construire et déployer des modèles

Construire et déployer des modèles? Permettez-moi de vous présenter mon ami R et l' apprentissage de la machine vue des tâches. :) Les modèles de base à explorer multinomial modèles (jetez un oeil à l' glmnet), les arbres de décision, et les machines à vecteurs de support. Vous pouvez utiliser les arbres de décision et les SVMs comme entrées pour un modèle multinomial (et les SVMs pourrait ne pas être nécessaire, après tout). Pour être honnête, cette partie est nébuleux: on pourrait faire cette modélisation comme déconnecté de la date de composants ou comme un processus d'améliorations, par exemple, obtenir l'année, si possible, puis les minutes (parce que la gamme est beaucoup plus grande que pour les heures, les jours, mois), puis le jour du mois, et enfin des heures et des mois. Essentiellement, j'avais pour but d'essayer d'identifier les "parties de temps" (analogue à certaines parties du discours) pour le numérique/chaîne de composants.

L'extraction des caractéristiques: - je voudrais essayer divise avec des points, des virgules, des barres obliques, des tirets, points, etc. Tout ce qui n'est pas une valeur numérique. Je serais alors en mesure de créer des ensembles de données de base sur les fonctions dans l'ordre et dans n'importe quel ordre (c'est à dire une valeur de l'indicateur de caractéristiques observées, en ignorant les positions).

Les données d'entraînement: Amazon Mechanical Turk.

Ou, vous savez quoi, il suffit de les ignorer tout de la programmation et de la statistique mumbo jumbo et envoyer le tout à Mechanical Turk. :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X