Bonjour,
J'ai deux colonnes de date dans as.POSIXct au format AAAA-MM-JJ HH: MM: SS. J'aimerais connaître la différence entre les deux, affichée au format Jours Heures: Secondes. Voici quelques données factices:
ab$time_difference<-difftime(ab$b, ab$a,units=c("days","hours","seconds"))
Ce qui donne ce bloc de données:
ab$time_difference<-difftime(ab$b, ab$a) ab a b time_difference 2018-03-20 11:52:25 AST 2018-04-09 18:39:38 AST 486.786944 hours 2018-03-20 12:51:25 AST 2018-06-23 19:13:14 AST 2286.363611 hours 2018-03-20 14:19:04 AST 2018-03-20 23:23:03 AST 9.066389 hours 2018-03-21 14:12:12 AST 2018-05-10 21:29:28 AST 1207.287778 hours 2018-03-21 12:09:22 AST 2018-03-22 03:17:23 AST 15.133611 hours 2018-03-21 15:28:01 AST 2018-05-12 00:19:39 AST 1232.860556 hours
Je voudrais faire la différence entre a et b, ou soustrayez le temps a du temps b pour obtenir une sortie de X jours X heures: X secondes.
J'ai utilisé difftime ci-dessous, ainsi que les unités définies différemment:
a b 2018-03-20 11:52:25 AST 2018-04-09 18:39:38 AST 2018-03-20 12:51:25 AST 2018-06-23 19:13:14 AST 2018-03-20 14:19:04 AST 2018-03-20 23:23:03 AST 2018-03-21 14:12:12 AST 2018-05-10 21:29:28 AST 2018-03-21 12:09:22 AST 2018-03-22 03:17:23 AST 2018-03-21 15:28:01 AST 2018-05-12 00:19:39 AST
J'ai également essayé ce qui suit:
a<-c("2018-03-20 11:52:25 AST", "2018-03-20 12:51:25 AST", "2018-03-20 14:19:04 AST", "2018-03-21 14:12:12 AST", "2018-03-21 12:09:22 AST", "2018-03-21 15:28:01 AST") b<-c("2018-04-09 18:39:38 AST", "2018-06-23 19:13:14 AST", "2018-03-20 23:23:03 AST", "2018-05-10 21:29:28 AST", "2018-03-22 03:17:23 AST", "2018-05-12 00:19:39 AST") ab<-data.frame(a,b)
Mais obtenez l'erreur que 'units' doit avoir une longueur de 1. Y a-t-il une commande différente que je devrais utiliser, ou y a-t-il un moyen pour difftime de produire une différence de temps plus exacte? p >
Merci!
4 Réponses :
La bibliothèque hms peut fournir une assistance ici:
Fmt <- function(x) UseMethod("Fmt") Fmt.difftime <- function(x) { units(x) <- "secs" x <- unclass(x) NextMethod() } Fmt.default <- function(x) { y <- abs(x) sprintf("%s%02d:%02d:%02d:%02d", ifelse(x < 0, "-", ""), # sign y %/% 86400, # days y %% 86400 %/% 3600, # hours y %% 3600 %/% 60, # minutes y %% 60 %/% 1) # seconds } a<-c("2018-03-20 11:52:25 AST", "2018-03-20 12:51:25 AST", "2018-03-20 14:19:04 AST", "2018-03-21 14:12:12 AST", "2018-03-21 12:09:22 AST", "2018-03-21 15:28:01 AST") b<-c("2018-04-09 18:39:38 AST", "2018-06-23 19:13:14 AST", "2018-03-20 23:23:03 AST", "2018-05-10 21:29:28 AST", "2018-03-22 03:17:23 AST", "2018-05-12 00:19:39 AST") ab<-data.frame(a,b) #Passing two dates to the function(s) Fmt(as.POSIXct(ab$b)-as.POSIXct(ab$a)) #Passing a time difference in seconds Fmt(difftime(ab$b, ab$a, units="secs"))
Voir cette question pour d'autres options: Sortie de difftime comme HH: MM: SS: mm dans R
Voici le code de la réponse ci-dessus pour votre problème:
XXX
La clé ici est d'exécuter le code pour les définitions de fonction au début de votre script afin que les fonctions soient alors disponibles pour utilisation.
Merci, cela fonctionne en reformatant la colonne de décalage horaire en heures: minutes: secondes, mais je ne peux pas aussi la mettre en forme en jours. J'ai également examiné la question que vous avez liée et essayé d'utiliser la fonction, mais je ne comprends pas très bien comment l'utiliser, et je n'ai pas pu la faire reformater ma colonne de données.
Merci pour la réponse et éditez @ Dave2e. J'ai exécuté le code, mais continue à recevoir le message d'erreur "Erreur dans * tmp *
$ diffs: l'opérateur $ n'est pas valide pour les vecteurs atomiques". J'ai essayé is.atomic et j'ai obtenu TRUE pour chaque colonne. Selon cette question, une erreur stackoverflow.com/questions/23299684/... Je dois utiliser Fmt (as.POSIXct (ab [" b "]) - as.POSIXct (ab [" a "]), cependant J'obtiens alors l'erreur "ne sais pas comment convertir 'tag_final [" last_pos "]' en classe" POSIXct ". Quand je fais str (ab), cela indique que ces colonnes sont dans POSIXct. Que me manque-t-il ici?
Si les colonnes sont de classe POSIXct, alors elles sont toutes prêtes pour un objet date-heure et vous devez utiliser la fonction difftime
. Si vous citez les noms de colonnes, vous devrez utiliser des doubles crochets Fmt (as.POSIXct (ab [["b"]]) - as.POSIXct (ab [["a"]])
require(lubridate) a<-c("2018-03-20 11:52:25 AST", "2018-03-20 12:51:25 AST", "2018-03-20 14:19:04 AST", "2018-03-21 14:12:12 AST", "2018-03-21 12:09:22 AST", "2018-03-21 15:28:01 AST") b<-c("2018-04-09 18:39:38 AST", "2018-06-23 19:13:14 AST", "2018-03-20 23:23:03 AST", "2018-05-10 21:29:28 AST", "2018-03-22 03:17:23 AST", "2018-05-12 00:19:39 AST") # Make df ab <- data.frame(a = as.POSIXct(a),b = as.POSIXct(b),stringsAsFactors = FALSE) # Time diff ab$time_difference <- ab$b - ab$a ab$time_difference <- as.duration(ab$time_difference) ab$time_difference 1 2018-03-20 11:52:25 2018-04-09 18:39:38 1752433s (~2.9 weeks) 2 2018-03-20 12:51:25 2018-06-23 19:13:14 8230909s (~13.61 weeks) 3 2018-03-20 14:19:04 2018-03-20 23:23:03 32639s (~9.07 hours) 4 2018-03-21 14:12:12 2018-05-10 21:29:28 4346236s (~7.19 weeks) 5 2018-03-21 12:09:22 2018-03-22 03:17:23 54481s (~15.13 hours) 6 2018-03-21 15:28:01 2018-05-12 00:19:39 4438298s (~7.34 weeks)
Comment un décalage horaire du même jour est-il égal à -785104d -7H -7M 0S
?
Puisque vous souhaitez des jours, des heures, des minutes, des secondes, nous pouvons obtenir ce résultat avec le package lubridate
:
> as.period(timespan, unit = "day") [1] "20d 6H 47M 13S" "95d 6H 21M 49S" "9H 3M 59S" "50d 7H 17M 16S" [5] "15H 8M 1S" "51d 8H 51M 38S"
Si vous le souhaitez, nous pouvons convertir des mois à jours en spécifiant la mise en forme comme suit:
a<-c("2018-03-20 11:52:25 AST", "2018-03-20 12:51:25 AST", "2018-03-20 14:19:04 AST", "2018-03-21 14:12:12 AST", "2018-03-21 12:09:22 AST", "2018-03-21 15:28:01 AST") b<-c("2018-04-09 18:39:38 AST", "2018-06-23 19:13:14 AST", "2018-03-20 23:23:03 AST", "2018-05-10 21:29:28 AST", "2018-03-22 03:17:23 AST", "2018-05-12 00:19:39 AST") a = as.POSIXct(a) b = as.POSIXct(b) library(lubridate) timespan = interval(ymd_hms(ab[,1]), ymd_hms(ab[,2])) > as.period(timespan) [1] "20d 6H 47M 13S" "3m 3d 6H 21M 49S" "9H 3M 59S" "1m 19d 7H 17M 16S" [5] "15H 8M 1S" "1m 20d 8H 51M 38S"
Utiliser un objet period
pour cela semble être une idée loin d'être idéale - " Parce que les périodes n'ont pas de longueur fixe, ils ne peuvent pas être convertis avec précision depuis et vers des objets Duration "
Je vous remercie. La deuxième valeur de la sortie a 3m et 21 M ... Est-ce que les minuscules m représentent des millisecondes? Si oui, existe-t-il un moyen de supprimer les millisecondes?
Le «m» minuscule représente des mois (puisque la différence entre les dates est si grande).
Ah, je vois, merci. Étant donné que les jours en mois varient, existe-t-il un moyen de faire passer les mois par défaut à jours? Donc, ma sortie serait juste des jours, des heures, des minutes, des secondes?
@ElizabethSmith: Oui, nous pouvons changer des mois en jours en spécifiant le formatage. J'ai édité ma réponse et ajouté un peu de code à la fin pour ce faire.
Merci beaucoup! C'est exactement ce que je recherche!
@ElizabethSmith: Je suis contente d'avoir pu aider :)
Utilisez sprintf
et l'arithmétique modulaire:
# first, be sure to specify units in difftime, or it will internally # choose units for each row # using 'secs' here since it's the lowest common denominator # wrapping as.double() to remove the class attribute which will # screw up dispatch to Ops below ab$time_difference <- as.double(difftime(ab$b, ab$a, units = 'secs')) # 3600 = 60*60 seconds in an hour; # 86400 = 3600*24 seconds in a day ab$hms = with(ab, sprintf('%d days; %d hours; %d seconds', time_difference %/% 86400L, (time_difference %% 86400L) %/% 3600L, time_difference %% 3600L)) ab$hms # [1] "20 days; 6 hours; 2833 seconds" "95 days; 6 hours; 1309 seconds" # [3] "0 days; 9 hours; 239 seconds" "50 days; 7 hours; 1036 seconds" # [5] "0 days; 15 hours; 481 seconds" "51 days; 8 hours; 3098 seconds"
J'ai choisi un format de sortie particulièrement verbeux juste pour l'illustration; les blocs de construction sont là pour rouler les vôtres, bien sûr, en gardant à l'esprit que vous devez remplacer % d
par % 02d
(par exemple) à gauche- 0 -pad la sortie à
2
chiffres.