it-swarm.com.de

Pandas csv als Zeichenfolgentyp lesen

Ich habe einen Datenrahmen mit alphanumerischen Schlüsseln, den ich als CSV speichern und später zurücklesen möchte. Aus verschiedenen Gründen muss ich diese Schlüsselspalte explizit als Zeichenfolgenformat lesen, ich habe Schlüssel, die streng numerisch oder noch schlimmer sind, Dinge wie: 1234E5, die Pandas als Float interpretiert. Dies macht offensichtlich der Schlüssel völlig nutzlos.

Das Problem ist, wenn ich einen String dtype für den Datenrahmen oder eine Spalte davon spezifiziere, bekomme ich nur Müll zurück. Ich habe hier einen Beispielcode:

df = pd.DataFrame(np.random.Rand(2,2),
                  index=['1A', '1B'],
                  columns=['A', 'B'])
df.to_csv(savefile)

Der Datenrahmen sieht folgendermaßen aus:

           A         B
1A  0.209059  0.275554
1B  0.742666  0.721165

Dann habe ich es so gelesen:

df_read = pd.read_csv(savefile, dtype=str, index_col=0)

und das Ergebnis ist:

   A  B
B  (  <

Ist das ein Problem mit meinem Computer oder etwas, was ich hier falsch mache, oder nur ein Fehler?

29
daver

Update: dies wurde behoben : von 0.11.1 übergibt man str/np.str entspricht der Verwendung von object.

Verwenden Sie das Objekt dtype:

In [11]: pd.read_csv('a', dtype=object, index_col=0)
Out[11]:
                      A                     B
1A  0.35633069074776547     0.745585398803751
1B  0.20037376323337375  0.013921830784260236

oder noch besser, geben Sie einfach keinen dtype an:

In [12]: pd.read_csv('a', index_col=0)
Out[12]:
           A         B
1A  0.356331  0.745585
1B  0.200374  0.013922

um jedoch den Typ-Sniffer zu umgehen und wirklich nur Zeichenfolgen zurückzugeben, ist die Verwendung von converters erforderlich:

In [13]: pd.read_csv('a', converters={i: str for i in range(100)})
Out[13]:
                      A                     B
1A  0.35633069074776547     0.745585398803751
1B  0.20037376323337375  0.013921830784260236

wo 100 ist eine Zahl, die Ihrer Gesamtzahl an Spalten entspricht oder größer ist.

Vermeiden Sie am besten den str dtype, siehe zum Beispiel hier .

35
Andy Hayden

Verwenden Sie einen Konverter, der für jede Spalte gilt, wenn Sie die Spalten vorher nicht kennen:

import pandas as pd

class StringConverter(dict):
    def __contains__(self, item):
        return True

    def __getitem__(self, item):
        return str

    def get(self, default=None):
        return str

pd.read_csv(file_or_buffer, converters=StringConverter())
2
DanielRS

Wie Anton T in seinem Kommentar sagte, verwandelt pandasobject Typen zufällig in float Typen unter Verwendung seines Typ-Sniffers, auch wenn Sie dtype=object, dtype=str Oder dtype=np.str.

Da Sie ein Funktionswörterbuch übergeben können, bei dem der Schlüssel ein Spaltenindex und der Wert eine Konvertierungsfunktion ist, können Sie so etwas tun (z. B. für 100 Spalten).

pd.read_csv('some_file.csv', converters={i: str for i in range(0, 100)})

Sie können sogar range(0, N) für N übergeben, das viel größer als die Anzahl der Spalten ist, wenn Sie nicht wissen, wie viele Spalten Sie lesen werden.

2
Chris Conlan