2017-10-15 2 views
1

Wie kann ich eine Ebene in multi-indizierten Spalten löschen, wenn ich drei Spalten in datetime umwandle? Das folgende Beispiel enthält nur drei Spalten, während in meinem Datumsrahmen natürlich mehr Spalten vorhanden sind und diese anderen Spalten zwei Ebenennamen verwenden.Pandas to_datetime mit multiindex

>>> import pandas as pd 
    >>> df = pd.DataFrame([[2010, 1, 2],[2011,1,3],[2012,2,3]]) 
    >>> df.columns = [['year', 'month', 'day'],['y', 'm', 'd']] 
    >>> print(df) 
     year month day 
      y  m d 
    0 2010  1 2 
    1 2011  1 3 
    2 2012  2 3 
    >>> pd.to_datetime(df[['year', 'month', 'day']]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib64/python2.7/site-packages/pandas/core/tools/datetimes.py", line 512, in to_datetime 
    result = _assemble_from_unit_mappings(arg, errors=errors) 
    File "/usr/lib64/python2.7/site-packages/pandas/core/tools/datetimes.py", line 582, in _assemble_from_unit_mappings 
    unit = {k: f(k) for k in arg.keys()} 
    File "/usr/lib64/python2.7/site-packages/pandas/core/tools/datetimes.py", line 582, in <dictcomp> 
    unit = {k: f(k) for k in arg.keys()} 
    File "/usr/lib64/python2.7/site-packages/pandas/core/tools/datetimes.py", line 577, in f 
    if value.lower() in _unit_map: 
AttributeError: 'tuple' object has no attribute 'lower' 

Edit: mehr Spalten hinzufügen zu erklären, besser:

>>> df = pd.DataFrame([[2010, 1, 2, 10, 2],[2011,1,3,11,3],[2012,2,3,12,2]]) 
>>> df.columns = [['year', 'month', 'day', 'temp', 'wind_speed'],['', '', '', 'degc','m/s']] 
>>> print(df) 
    year month day temp wind_speed 
        degc  m/s 
0 2010  1 2 10   2 
1 2011  1 3 11   3 
2 2012  2 3 12   2 

Was ich brauche, ist zunächst drei Spalten Datetime-Index zu kombinieren, so dass zwei letzten Spalten mit Daten.

+0

Können Sie mehr Daten mit den gewünschten Ausgang hinzufügen? – jezrael

+0

Danke, ich füge auch eine Lösung dafür hinzu. – jezrael

Antwort

3

Verwenden droplevel für die zweite Ebene entfernen:

df.columns = df.columns.droplevel(1) 
df = pd.to_datetime(df[['year', 'month', 'day']]) 
print (df) 
0 2010-01-02 
1 2011-01-03 
2 2012-02-03 
dtype: datetime64[ns] 

Wenn nur 3 columns:

df.columns = df.columns.droplevel(1) 
df = pd.to_datetime(df) 
print (df) 

0 2010-01-02 
1 2011-01-03 
2 2012-02-03 
dtype: datetime64[ns] 

Wenn mehrere Spalten:

df = pd.DataFrame([[2010, 1, 2,3],[2011,1,3,5],[2012,2,3,7]]) 
df.columns = [['year', 'month', 'day','a'],['y', 'm', 'd', 'b']] 
print(df) 
    year month day a 
     y  m d b 
0 2010  1 2 3 
1 2011  1 3 5 
2 2012  2 3 7 

#select datetime columns only 
df1 = df[['year', 'month', 'day']] 
df1.columns = df1.columns.droplevel(1) 
print (df1) 
    year month day 
0 2010  1 2 
1 2011  1 3 
2 2012  2 3 

#convert to Series 
s1 = pd.to_datetime(df1) 
#set new MultiIndex 
s1.name=('date','dat') 
print (s1) 
0 2010-01-02 
1 2011-01-03 
2 2012-02-03 
Name: (date, dat), dtype: datetime64[ns] 

#remove original columns and add new datetime Series 
df = df.drop(['year', 'month', 'day'], axis=1, level=0).join(s1) 
print (df) 
    a  date 
    b  dat 
0 3 2010-01-02 
1 5 2011-01-03 
2 7 2012-02-03 

Eine andere Lösung mit transponieren, sollten slowier in großen Datenrahmen sein:

df1 = df[['year', 'month', 'day']] 
s1 = pd.to_datetime(df1.T.reset_index(drop=True, level=1).T).rename(('date', 'dat')) 
print (s1) 
0 2010-01-02 
1 2011-01-03 
2 2012-02-03 
Name: (date, dat), dtype: datetime64[ns] 

df1 = df.join(s1) 
print (df1) 
    year month day temp wind_speed  date 
        degc  m/s  dat 
0 2010  1 2 10   2 2010-01-02 
1 2011  1 3 11   3 2011-01-03 
2 2012  2 3 12   2 2012-02-03 
+0

Danke @jezrael für Ihre Hilfe. Es funktioniert, irgendwie dachte ich nur, es könnte in einem Schritt gemacht werden. Aber das ist auch sehr gut. – crayxt