Hoe om te zetten kolommen in een datetime kolom in panda ‘ s?

Ik heb een dataframe waar de eerste 3 kolommen ‘MAAND’, ‘DAG’, ‘JAAR’

In elke kolom is er een geheel getal.
Is er een Pythonic manier om te converteren van alle drie de kolommen in datetimes terwijl er in het dataframe?

Van:

M    D    Y    Apples   Oranges
5    6  1990      12        3
5    7  1990      14        4
5    8  1990      15       34
5    9  1990      23       21

in:

Datetimes    Apples   Oranges
1990-6-5        12        3
1990-7-5        14        4
1990-8-5        15       34
1990-9-5        23       21
InformationsquelleAutor user1367204 | 2013-10-13



8 Replies
  1. 43

    In 0.13 (zeer snel), dit is sterk geoptimaliseerd en heel snel (maar nog steeds vrij snel in 0.12); beide ordes van grootte sneller dan looping

    In [3]: df
    Out[3]: 
       M  D     Y  Apples  Oranges
    0  5  6  1990      12        3
    1  5  7  1990      14        4
    2  5  8  1990      15       34
    3  5  9  1990      23       21
    
    In [4]: df.dtypes
    Out[4]: 
    M          int64
    D          int64
    Y          int64
    Apples     int64
    Oranges    int64
    dtype: object
    
    # in 0.12, use this
    In [5]: pd.to_datetime((df.Y*10000+df.M*100+df.D).apply(str),format='%Y%m%d')
    
    # in 0.13 the above or this will work
    In [5]: pd.to_datetime(df.Y*10000+df.M*100+df.D,format='%Y%m%d')
    Out[5]: 
    0   1990-05-06 00:00:00
    1   1990-05-07 00:00:00
    2   1990-05-08 00:00:00
    3   1990-05-09 00:00:00
    dtype: datetime64[ns]
    • Dank je, maar ik krijg de foutmelding: TypeError: verwachte string of buffer
    • Ik bewerkte u tonen hoe om dit te doen in 0.12. to_datetime moet de gegevens stringified.
    • Bedankt, het werkte, kunt u uitleggen wat het doel van de *10000 en de *100 zijn? Nevermind, het doel is om te zetten in 2011, 5, 3, in 20110503 die gemakkelijk kan worden gelezen. Bedankt!!
    • Een woord als 0.13 beschikbaar zal zijn? Een week? Een maand? Een jaar?
    • yep – in feite is dit de snelste methode omdat deze zijn gevectoriseerd numerieke operaties en de conversie te datetime niet rondreis door strijkers
    • 0.13 is over 2 weken of zo
    • Ik zou geïnteresseerd zijn om te zien of krijg je betere resultaten van pd.to_datetime(dict(year=df.Y, month=df.M, day=df.D))
    • Dit is een oude antwoord, maar de vraag is de eerste in de google rankings. Is er iets nieuws op dit front nu?
    • volgens %timeit, ze zijn ongeveer hetzelfde – de numerieke versie is misschien 5-10% sneller op de dataset die ik heb gebruikt. Ik zal gebruik maken van de dict-versie, want het is beter leesbaar.

  2. 62

    In versie 0.18.1 kunt u gebruik maken van to_datetime, maar:

    • namen van de kolommen moeten worden year, month, day, hour, minute en second:
    • minimale kolommen zijn year, month en day

    Voorbeeld:

    import pandas as pd
    
    df = pd.DataFrame({'year': [2015, 2016],
                       'month': [2, 3],
                        'day': [4, 5],
                        'hour': [2, 3],
                        'minute': [10, 30],
                        'second': [21,25]})
    
    print df
       day  hour  minute  month  second  year
    0    4     2      10      2      21  2015
    1    5     3      30      3      25  2016
    
    print pd.to_datetime(df[['year', 'month', 'day']])
    0   2015-02-04
    1   2016-03-05
    dtype: datetime64[ns]
    
    print pd.to_datetime(df[['year', 'month', 'day', 'hour']])
    0   2015-02-04 02:00:00
    1   2016-03-05 03:00:00
    dtype: datetime64[ns]
    
    print pd.to_datetime(df[['year', 'month', 'day', 'hour', 'minute']])
    0   2015-02-04 02:10:00
    1   2016-03-05 03:30:00
    dtype: datetime64[ns]
    
    print pd.to_datetime(df)
    0   2015-02-04 02:10:21
    1   2016-03-05 03:30:25
    dtype: datetime64[ns]

    Een andere oplossing is om te zetten naar dictionary:

    print df
       M  D     Y  Apples  Oranges
    0  5  6  1990      12        3
    1  5  7  1990      14        4
    2  5  8  1990      15       34
    3  5  9  1990      23       21
    
    print pd.to_datetime(dict(year=df.Y, month=df.M, day=df.D))
    0   1990-05-06
    1   1990-05-07
    2   1990-05-08
    3   1990-05-09
    dtype: datetime64[ns]
  3. 7

    Hier is een alternatief dat gebruik maakt van NumPy datetime64 en timedelta64 rekenkundige. Het lijkt een beetje sneller voor kleine DataFrames en veel sneller en voor grotere DataFrames:

    import numpy as np
    import pandas as pd
    
    df = pd.DataFrame({'M':[1,2,3,4], 'D':[6,7,8,9], 'Y':[1990,1991,1992,1993]})
    #    D  M     Y
    # 0  6  1  1990
    # 1  7  2  1991
    # 2  8  3  1992
    # 3  9  4  1993
    
    y = np.array(df['Y']-1970, dtype='<M8[Y]')
    m = np.array(df['M']-1, dtype='<m8[M]')
    d = np.array(df['D']-1, dtype='<m8[D]')
    dates2 = pd.Series(y+m+d)
    # 0   1990-01-06
    # 1   1991-02-07
    # 2   1992-03-08
    # 3   1993-04-09
    # dtype: datetime64[ns]

    In [214]: df = pd.concat([df]*1000)
    
    In [215]: %timeit pd.to_datetime((df['Y']*10000+df['M']*100+df['D']).astype('int'), format='%Y%m%d')
    100 loops, best of 3: 4.87 ms per loop
    
    In [216]: %timeit pd.Series(np.array(df['Y']-1970, dtype='<M8[Y]')+np.array(df['M']-1, dtype='<m8[M]')+np.array(df['D']-1, dtype='<m8[D]'))
    1000 loops, best of 3: 839 µs per loop

    Hier is een helper functie om dit makkelijker te maken om gebruik:

    def combine64(years, months=1, days=1, weeks=None, hours=None, minutes=None,
                  seconds=None, milliseconds=None, microseconds=None, nanoseconds=None):
        years = np.asarray(years) - 1970
        months = np.asarray(months) - 1
        days = np.asarray(days) - 1
        types = ('<M8[Y]', '<m8[M]', '<m8[D]', '<m8[W]', '<m8[h]',
                 '<m8[m]', '<m8[s]', '<m8[ms]', '<m8[us]', '<m8[ns]')
        vals = (years, months, days, weeks, hours, minutes, seconds,
                milliseconds, microseconds, nanoseconds)
        return sum(np.asarray(v, dtype=t) for t, v in zip(types, vals)
                   if v is not None)
    
    In [437]: combine64(df['Y'], df['M'], df['D'])
    Out[437]: array(['1990-01-06', '1991-02-07', '1992-03-08', '1993-04-09'], dtype='datetime64[D]')
    • Ik denk dat dit, of deze functionaliteit tenminste, het zou een mooie uitbreiding voor panda ‘ s. We moeten gewoon uitzoeken van een API.
    • Ja, het hebben om dingen te doen zoals *10000 of -1970 is dom. We moeten zeker in staat zijn te combineren standaard tijd vormen in veel eenvoudigere manier. (En als er een betere manier, maar niemand van ons weet, dan is er ten minste een doc-bug..)
  4. 2

    Ik opnieuw benaderde het probleem en ik denk dat ik een oplossing gevonden. Ik geïnitialiseerd het csv-bestand op de volgende manier:

    pandas_object = DataFrame(read_csv('/Path/to/csv/file', parse_dates=True, index_col = [2,0,1] ))

    Waar:

    index_col = [2,0,1]

    vertegenwoordigt de kolommen van de [dag, maand, jaar]

    Enige probleem nu is dat ik nu drie nieuwe index kolommen, één vertegenwoordigen van het jaar, nog een maand, en een andere dag.

    • probeer parse_dates=[[2,0,1]] (let op de dubbele haakjes. Neem een kijkje op de doctstring op read_csv voor een voorbeeld.
  5. 1
     [pd.to_datetime(str(a)+str(b)+str(c),
                     format='%m%d%Y'
                    ) for a,b,c in zip(df.M, df.D, df.Y)]
  6. 0

    Zetten het dataframe aan snaren voor een eenvoudige string concatenatie:

    df=df.astype(str)

    vervolgens zetten om datetime geef het formaat:

    df.index=pd.to_datetime(df.Y+df.M+df.D,format="%Y%m%d")

    die vervangt de index in plaats van het creëren van een nieuwe kolom.

  7. 0

    Stel u hebt een woordenboek foo met elke kolom van de data in parallel. Als dat zo is, hier is uw one-liner:

    >>> from datetime import datetime
    >>> foo = {"M": [1,2,3], "D":[30,30,21], "Y":[1980,1981,1982]}
    >>>
    >>> df = pd.DataFrame({"Datetime": [datetime(y,m,d) for y,m,d in zip(foo["Y"],foo["M"],foo["D"])]})

    Het hart van het zijn dit bit:

    >>> [datetime(y,m,d) for y,m,d in zip(foo["Y"],foo["M"],foo["D"])]
    [datetime.datetime(1980, 1, 30, 0, 0), datetime.datetime(1981, 2, 28, 0, 0), datetime.datetime(1982, 3, 21, 0, 0)]

    Dit is het soort ding zip voor gemaakt is. Het duurt parallel lijsten en zet ze om in tupels. Dan krijgen ze tupel uitgepakt (de for y,m,d in beetje) door de lijst-comprehensie er, vervolgens in de datetime object constructor.

    pandas lijkt blij met de datum /tijd-objecten.

  8. -1

    Zelfs betere manier om dat te doen is als volgt:

    import pandas as pd
    
    import datetime
    
    dataset = pd.read_csv('dataset.csv')
    
    date=dataset.apply(lambda x: datetime.date(int(x['Yr']), x['Mo'], x['Dy']),axis=1)
    
    date = pd.to_datetime(date)
    
    dataset = dataset.drop(columns=['Yr', 'Mo', 'Dy'])
    
    dataset.insert(0, 'Date', date)
    
    dataset.head()

    • Voeg een omschrijving of toelichting op wat u doet in deze code.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *