2016-09-20 3 views
1

Ich habe Probleme mit pandas.DataFrame 's Konstruktor und mit dem dtype Argument. Ich möchte String-Werte beibehalten, aber die folgenden Snippets werden immer in einen numerischen Typ umgewandelt und ergeben dann NaN s.Einstellung pandas.DataFrame Zeichenfolge dtype (nicht dateibasiert)

from __future__ import unicode_literals 
from __future__ import print_function 


import numpy as np 
import pandas as pd 


def main(): 
    columns = ['great', 'good', 'average', 'bad', 'horrible'] 
    # minimal example, dates are coming (as strings) from some 
    # non-file source. 
    example_data = { 
     'alice': ['', '', '', '2016-05-24', ''], 
     'bob': ['', '2015-01-02', '', '', '2012-09-15'], 
     'eve': ['2011-12-31', '', '1998-08-13', '', ''], 
    } 

    # first pass, yields dataframe full of NaNs 
    df = pd.DataFrame(data=example_data, index=example_data.keys(), 
     columns=columns, dtype=str) #or string, 'str', 'string', 'object' 
    print(df.dtypes) 
    print(df) 
    print() 

    # based on https://github.com/pydata/pandas/blob/master/pandas/core/frame.py 
    # and https://github.com/pydata/pandas/blob/37f95cef85834207db0930e863341efb285e38a2/pandas/types/common.py 
    # we're ultimately feeding dtype to numpy's dtype, so let's just use that: 
    #  (using np.dtype('S10') and converting to str doesn't work either) 
    df = pd.DataFrame(data=example_data, index=example_data.keys(), 
     columns=columns, dtype=np.dtype('U')) 
    print(df.dtypes) 
    print(df) # still full of NaNs... =(



if __name__ == '__main__': 
    main() 

Welcher Wert (e) von dtypes wird Zeichenfolge in dem Datenrahmen bewahren?

Referenz:

$ python --version

2.7.12

$ pip2 Liste | grep Pandas

Pandas (0.18.1)

$ pip2 Liste | grep numpy

numpy (1.11.1)

Antwort

1

Für den speziellen Fall im OP können Sie die DataFrame.from_dict() constructor verwenden (siehe auch den Abschnitt Alternate Constructors der Dataframe-Dokumentation).

from __future__ import unicode_literals 
from __future__ import print_function 

import pandas as pd 

columns = ['great', 'good', 'average', 'bad', 'horrible'] 
example_data = { 
    'alice': ['', '', '', '2016-05-24', ''], 
    'bob': ['', '2015-01-02', '', '', '2012-09-15'], 
    'eve': ['2011-12-31', '', '1998-08-13', '', ''], 
} 
df = pd.DataFrame.from_dict(example_data, orient='index') 
df.columns = columns 

print(df.dtypes) 
# great  object 
# good  object 
# average  object 
# bad   object 
# horrible object 
# dtype: object 

print(df) 
#    great  good  average   bad horrible 
# bob    2015-01-02       2012-09-15 
# eve 2011-12-31    1998-08-13       
# alice          2016-05-24  

können Sie sogar dtype=str in DataFrame.from_dict() — angeben, obwohl es in diesem Beispiel nicht notwendig ist.

EDIT: Der Datenrahmen Konstruktor interpretiert ein Wörterbuch als eine Sammlung von Spalten:

print(pd.DataFrame(example_data)) 

#   alice   bob   eve 
# 0       2011-12-31 
# 1    2015-01-02    
# 2       1998-08-13 
# 3 2016-05-24       
# 4    2012-09-15    

(Ich bin die data= fallen, da data das erste Argument in der Signatur der Funktion ist sowieso). Ihr Code verwechselt Zeilen und Spalten:

print(pd.DataFrame(example_data, index=example_data.keys(), columns=columns)) 

#  great good average bad horrible 
# alice NaN NaN  NaN NaN  NaN 
# bob  NaN NaN  NaN NaN  NaN 
# eve  NaN NaN  NaN NaN  NaN 

(obwohl ich nicht ganz sicher bin, wie es endet Sie einen Datenrahmen von NaN s geben).Es wäre richtig

print(pd.DataFrame(example_data, columns=example_data.keys(), index=columns)) 

#    alice   bob   eve 
# great        2011-12-31 
# good     2015-01-02    
# average       1998-08-13 
# bad  2016-05-24       
# horrible    2012-09-15 

Angabe der Spaltennamen zu tun, ist eigentlich unnötig — sie bereits aus dem Wörterbuch analysiert werden:

print(pd.DataFrame(example_data, index=columns)) 

#    alice   bob   eve 
# great        2011-12-31 
# good     2015-01-02    
# average       1998-08-13 
# bad  2016-05-24       
# horrible    2012-09-15      

Was Sie wollen, ist eigentlich die dieser — transponieren, so dass Sie kann auch diese Transponierte nehmen!

print(pd.DataFrame(data=example_data, index=columns).T) 

#    great  good  average   bad horrible 
# alice          2016-05-24    
# bob    2015-01-02       2012-09-15 
# eve 2011-12-31    1998-08-13    
+0

Yay, das funktioniert. Kennst du aus Neugier, warum das funktioniert, während das Original nicht funktioniert? Da der übliche Konstruktor Wörterbücher aufnehmen kann, ist mir nicht klar, warum sich der 'from_dict'-Konstruktor so anders verhält. – everial

+1

@everial: Nachdem ich es genauer betrachtet habe, habe ich herausgefunden, was Sie falsch gemacht haben --- siehe Bearbeiten. –

+0

danke für die detaillierte Folge ... du kannst sehen wie ich Erfahrung mit Pandas habe. =) – everial

0

Dies ist keine richtige Antwort, aber während Sie eine von jemand anderem bekommen, habe ich bemerkt, dass die Verwendung von read_csv Funktion alles funktioniert.

Also, wenn Sie Ihre Daten in einer Datei .csvmyData.csv, wie dies genannt platzieren:

great,good,average,bad,horrible 
alice,,,,2016-05-24, 
bob,,2015-01-02,,,2012-09-15 
eve,2011-12-31,,1998-08-13,, 

und tun

df = pd.read_csv('blablah/myData.csv') 

es wird die Saiten halten, wie sie sind! in der CSV-Datei oder jedes andere Zeichen/Marker

 great  good  average  bad  horrible 
alice NaN  NaN  NaN  2016-05-24  NaN 
bob  NaN 2015-01-02 NaN   NaN  2012-09-15 
eve 2011-12-31 NaN 1998-08-13  NaN   NaN 

, wenn Sie möchten, können die leeren Werte als Raum gestellt werden.

+0

Danke für die Anregung, aber wie in der Probe erwähnt ist die Daten derzeit nicht in einer Datei - ich weiß nicht wirklich einfach schreiben will, um es mit 'read_csv' erneut zu lesen, wenn das sein kann vermieden werden. – everial

Verwandte Themen