web-dev-qa-db-fra.com

Arrondi à la seconde près - Python

J'ai un grand ensemble de données avec plus de 500 000 horodatages qui ressemblent à ceci:

date        time
2017-06-25 00:31:53.993
2017-06-25 00:32:31.224
2017-06-25 00:33:11.223
2017-06-25 00:33:53.876
2017-06-25 00:34:31.219
2017-06-25 00:35:12.634 

Comment arrondir ces horodatages à la seconde près?

Mon code ressemble à ceci:

readcsv = pd.read_csv(filename)
log_date = readcsv.date
log_time = readcsv.time

readcsv['date'] = pd.to_datetime(readcsv['date']).dt.date
readcsv['time'] = pd.to_datetime(readcsv['time']).dt.time
timestamp = [datetime.datetime.combine(log_date[i],log_time[i]) for i in range(len(log_date))]

Alors maintenant, j'ai combiné les dates et les heures dans une liste d'objets datetime.datetime Qui ressemble à ceci:

datetime.datetime(2017,6,25,00,31,53,993000)
datetime.datetime(2017,6,25,00,32,31,224000)
datetime.datetime(2017,6,25,00,33,11,223000)
datetime.datetime(2017,6,25,00,33,53,876000)
datetime.datetime(2017,6,25,00,34,31,219000)
datetime.datetime(2017,6,25,00,35,12,634000)

Où dois-je aller d'ici? La fonction df.timestamp.dt.round('1s') ne semble pas fonctionner? De plus, lorsque j'utilisais .split() J'avais des problèmes lorsque les secondes et les minutes dépassaient 59

Merci beaucoup

11
Jetman

En utilisant for loop Et str.split():

dts = ['2017-06-25 00:31:53.993',
       '2017-06-25 00:32:31.224',
       '2017-06-25 00:33:11.223',
       '2017-06-25 00:33:53.876',
       '2017-06-25 00:34:31.219',
       '2017-06-25 00:35:12.634']

for item in dts:
    date = item.split()[0]
    h, m, s = [item.split()[1].split(':')[0],
               item.split()[1].split(':')[1],
               str(round(float(item.split()[1].split(':')[-1])))]

    print(date + ' ' + h + ':' + m + ':' + s)

2017-06-25 00:31:54
2017-06-25 00:32:31
2017-06-25 00:33:11
2017-06-25 00:33:54
2017-06-25 00:34:31
2017-06-25 00:35:13
>>> 

Vous pouvez transformer cela en fonction:

def round_seconds(dts):
    result = []
    for item in dts:
        date = item.split()[0]
        h, m, s = [item.split()[1].split(':')[0],
                   item.split()[1].split(':')[1],
                   str(round(float(item.split()[1].split(':')[-1])))]
        result.append(date + ' ' + h + ':' + m + ':' + s)

    return result

Test de la fonction:

dts = ['2017-06-25 00:31:53.993',
       '2017-06-25 00:32:31.224',
       '2017-06-25 00:33:11.223',
       '2017-06-25 00:33:53.876',
       '2017-06-25 00:34:31.219',
       '2017-06-25 00:35:12.634']

from pprint import pprint

pprint(round_seconds(dts))

['2017-06-25 00:31:54',
 '2017-06-25 00:32:31',
 '2017-06-25 00:33:11',
 '2017-06-25 00:33:54',
 '2017-06-25 00:34:31',
 '2017-06-25 00:35:13']
>>> 

Comme vous semblez utiliser Python 2.7, pour supprimer les zéros de fin, vous devrez peut-être modifier:

str(round(float(item.split()[1].split(':')[-1])))

à

str(round(float(item.split()[1].split(':')[-1]))).rstrip('0').rstrip('.')

Je viens d'essayer la fonction avec Python 2.7 à repl.it et elle a fonctionné comme prévu.

0
Srisaila

Sans package supplémentaire, un objet datetime peut être arrondi à la seconde près avec la fonction simple suivante:

import datetime

def roundSeconds(dateTimeObject):
    newDateTime = dateTimeObject

    if newDateTime.microsecond >= 500000:
        newDateTime = newDateTime + datetime.timedelta(seconds=1)

    return newDateTime.replace(microsecond=0)
11
electrovir

Si vous utilisez des pandas, vous pouvez simplement round les données à la seconde près en utilisant dt.round -

df

                timestamp
0 2017-06-25 00:31:53.993
1 2017-06-25 00:32:31.224
2 2017-06-25 00:33:11.223
3 2017-06-25 00:33:53.876
4 2017-06-25 00:34:31.219
5 2017-06-25 00:35:12.634

df.timestamp.dt.round('1s')

0   2017-06-25 00:31:54
1   2017-06-25 00:32:31
2   2017-06-25 00:33:11
3   2017-06-25 00:33:54
4   2017-06-25 00:34:31
5   2017-06-25 00:35:13
Name: timestamp, dtype: datetime64[ns]

Si timestamp n'est pas une colonne datetime, convertissez-la d'abord, en utilisant pd.to_datetime -

df.timestamp = pd.to_datetime(df.timestamp)

Ensuite, dt.round devrait marcher.

4
cs95

La question ne dit pas comment vous voulez arrondir. L'arrondi serait souvent approprié pour une fonction de temps. Ce ne sont pas des statistiques.

rounded_down_datetime = raw_datetime.replace(microsecond=0) 
2
mike rodent

Si vous stockez un ensemble de données dans un fichier, vous pouvez faire ceci:

with open('../dataset.txt') as fp:
    line = fp.readline()
    cnt = 1
    while line:
        line = fp.readline()
        print "\n" + line.strip()
        sec = line[line.rfind(':') + 1:len(line)]
        rounded_num = int(round(float(sec)))
        print line[0:line.rfind(':') + 1] + str(rounded_num)
        print abs(float(sec) - rounded_num)
        cnt += 1

Si vous stockez un ensemble de données dans une liste:

dts = ['2017-06-25 00:31:53.993',
   '2017-06-25 00:32:31.224',
   '2017-06-25 00:33:11.223',
   '2017-06-25 00:33:53.876',
   '2017-06-25 00:34:31.219',
   '2017-06-25 00:35:12.634']

for i in dts:
    line = i
    print "\n" + line.strip()
    sec = line[line.rfind(':') + 1:len(line)]
    rounded_num = int(round(float(sec)))
    print line[0:line.rfind(':') + 1] + str(rounded_num)
    print abs(float(sec) - rounded_num)
1
Rudradev Pal

Version alternative de la solution de @electrovir:

import datetime

def roundSeconds(dateTimeObject):
    newDateTime = dateTimeObject + datetime.timedelta(seconds=.5)
    return newDateTime.replace(microsecond=0)
0
gerardw

Si quelqu'un veut arrondir un seul élément datetime à la seconde près, celui-ci fonctionne très bien:

pandas.to_datetime(your_datetime_item).round('1s')
0
Maciej Gumułka

Une solution élégante qui ne nécessite que le module datetime standard.

import datetime

            currentimemili = datetime.datetime.now()
            currenttimesecs = currentimemili - \
                datetime.timedelta(microseconds=currentimemili.microsecond)
            print(currenttimesecs)
0
Gerardsson