Ich habe einen n- mal- m Pandas DataFrame df
wie folgt definiert. (Ich weiß, dass dies nicht der beste Weg ist, dies zu tun. Es ist sinnvoll für das, was ich in meinem eigentlichen Code versuche, aber das wäre TMI für diesen Beitrag. Nehmen Sie also einfach mein Wort, dass dieser Ansatz in meinem speziellen Szenario funktioniert .)
>>> df = DataFrame(columns=['col1'])
>>> df.append(Series([None]), ignore_index=True)
>>> df
Empty DataFrame
Columns: [col1]
Index: []
Ich habe Listen in den Zellen dieses DataFrame wie folgt gespeichert.
>>> df['column1'][0] = [1.23, 2.34]
>>> df
col1
0 [1, 2]
Aus irgendeinem Grund hat der DataFrame diese Liste als Zeichenfolge anstelle einer Liste gespeichert.
>>> df['column1'][0]
'[1.23, 2.34]'
Ich habe 2 Fragen an Sie.
- Warum speichert der DataFrame eine Liste als Zeichenfolge und gibt es einen Weg, um dieses Verhalten zu umgehen?
- Wenn nicht, gibt es dann eine pythonische Möglichkeit, diese Zeichenfolge in eine Liste umzuwandeln?
Aktualisieren
Der von mir verwendete DataFrame wurde gespeichert und aus einem CSV-Format geladen. Dieses Format konvertierte die Liste anstelle des DataFrame selbst von einer Zeichenfolge in ein Literal.
Antworten:
Wie Sie bereits betont haben, kann dies häufig beim Speichern und Laden von Pandas DataFrames als
.csv
Dateien auftreten, bei denen es sich um ein Textformat handelt.In Ihrem Fall geschah dies, weil Listenobjekte eine Zeichenfolgendarstellung haben, sodass sie als
.csv
Dateien gespeichert werden können. Das Laden des.csv
wird dann diese Zeichenfolgendarstellung ergeben.Wenn Sie die tatsächlichen Objekte speichern möchten, sollten Sie verwenden
DataFrame.to_pickle()
(Hinweis: Objekte müssen auswählbar sein!).Um Ihre zweite Frage zu beantworten, können Sie sie zurückkonvertieren mit
ast.literal_eval
:>>> from ast import literal_eval >>> literal_eval('[1.23, 2.34]') [1.23, 2.34]
quelle
list
umgewandeltstring
mitto_csv
gefolgt vonfrom_csv
in Version 0.17.1.Sie können Pandas direkt verwenden -
df = pd.read_csv(df_name, converters={'column_name': eval})
Dadurch wird diese Spalte als entsprechender D-Typ in Python anstelle einer Zeichenfolge gelesen.
quelle
Ich bin gerade auf dieses Problem gestoßen und es gibt eine sehr einfache Lösung ( pandas.eval () ). Ich benutze Pandas 0.20.0.
# SETUP import pandas as pd import io csv = io.StringIO(u''' id list A1 [1,2] A2 [3,4] A3 [5,6] ''') df = pd.read_csv(csv, delim_whitespace = True) # TYPE CHECK <type 'str'> print type(df.at[0, 'list']) # MAIN CONVERSION df['list'] = pd.eval(df['list']) # TYPE CHECK <type 'list'> print type(df.at[0, 'list'])
quelle
1) Es gibt einen Weg, um dieses Verhalten zu umgehen. Verwenden Sie loc hilft hier.
>>> import pandas as pd >>> df = pd.DataFrame(columns=['column1']) >>> df = df.append(pd.Series(data = {'column1':[None]}), ignore_index = True) column1 0 [None] >>> # Add list to index 0 in column1 >>> df.loc[0,'column1'] = [1.23, 2.34] >>> print(df.loc[0, 'column1']) [1.23, 2.34]
2) Pythonische Methode zum Konvertieren dieser Zeichenfolge in eine Liste. (Dies ist wahrscheinlich das, was Sie möchten, da der von Ihnen verwendete DataFrame gespeichert und aus einem CSV-Format geladen wurde. Hierfür gibt es einige Lösungen.) Dies ist eine Ergänzung zur Antwort von pshep123.
from ast import literal_eval import pandas as pd csv = io.StringIO(u''' id list A1 [1,2] A2 [3,4] A3 [5,6] ''') df = pd.read_csv(csv, delim_whitespace = True) # Output is a string df.loc[0, 'list'] '[1,2]' # Convert entire column to a list df.loc[:,'list'] = df.loc[:,'list'].apply(lambda x: literal_eval(x)) # Output is a list df.loc[0, 'list'] [1, 2]
quelle
apply
Methode verwendet die Eingabe jeder Zeile innerhalb der Funktion, die Sie übergeben. Schreiben Sie einfach.apply(literal_eval)
. Reservieren Sie das Lambda für eine kompliziertere Logik.df.list = df.list.apply(literal_eval)
Ich hatte das gleiche Problem. Beim Speichern einer Datenrahmen-Listenspalte in einer CSV-Datei mit df.to_csv () werden Listenspalten in eine Zeichenfolge konvertiert, z. B. "[42, 42, 42]" anstelle von [42, 42, 42].
Die Antwort von Alex ist korrekt und Sie können
literal_eval
die Zeichenfolge wieder in eine Liste konvertieren. Das Problem bei diesem Ansatz besteht darin, dass Sie eine zusätzliche Bibliothek importieren und die Funktion anwenden oder Ihrem Datenrahmen zuordnen müssen. Der einfachere Weg ist, Pandas zu zwingen, die Spalte als Python-Objekt (dtype) zu lesen.df["col1"].astype('O')
Das O wird für Python-Objekte einschließlich Listen verwendet. Mehr Infos hier . Bitte beachten Sie, dass diese Methode fehlschlägt, wenn Sie leere Listenzeichenfolgen analysieren: "[]"
Alternativ können Sie auch eine Funktion auf Ihre Spalte anwenden (diese ist für ganze Zahlen):
def stringToList(string): # input format : "[42, 42, 42]" , note the spaces after the commas, in this case I have a list of integers string = string[1:len(string)-1] try: if len(string) != 0: tempList = string.split(", ") newList = list(map(lambda x: int(x), tempList)) else: newList = [] except: newList = [-9999] return(newList) df["col1"] = df["col1"].apply(lambda x: stringToList(x))
quelle
Nur als Referenz ... Pandas konvertieren keine Listen in Zeichenfolgen. ..
In [29]: data2 = [{'a': [1, 5], 'b': 2}, {'a': 5, 'b': 10, 'c': 20}] In [30]: df = pd.DataFrame(data2) In [31]: df Out[31]: a b c 0 [1, 5] 2 NaN 1 5 10 20 In [32]: df['a'][0], type(df['a'][0]) Out[32]: ([1, 5], list) In [33]: pd.__version__ Out[33]: '0.12.0'
quelle
ast.literal_eval
diese Option, um eine Zeichenfolge mit einem Python-Literal oder einer Containeranzeige sicher auszuwerten.Es ist Teil der Standardbibliothek
Verwenden Sie pythons eval () vs. ast.literal_eval ()? erklärt, warum
literal_eval
sicherer ist als zu verwendeneval
.Beispiele:
literal_eval("[1.23, 2.34]")
funktioniertliteral_eval("['KB4523205','KB4519569','KB4503308']")
funktioniertliteral_eval("[KB4523205, KB4519569, KB4503308]")
funktioniert nicht (keine Anführungszeichen um diestr
Werte)converters
Parameters vonpandas.read_csv
.Daten in
test.csv
col1 "[1.23, 2.34]" "['KB4523205','KB4519569','KB4503308']"
Konvertieren Sie die Spalte beim Erstellen der CSV
from ast import literal_eval import pandas as pd # convert the column during import df = pd.read_csv('test.csv', converters={'col1': literal_eval}) # display(df) col1 0 [1.23, 2.34] 1 [KB4523205, KB4519569, KB4503308] # check type print(type(df.iloc[0, 0])) list print(type(df.iloc[1, 0])) list
Konvertieren Sie die Spalte eines vorhandenen Datenrahmens
quelle
Ein einfacher Hack, den ich verwendet habe, besteht darin, eine Lambda-Funktion aufzurufen, die das erste und das letzte Element (die Listenklammern in str-Form) indiziert und die Split-Methode aufruft, gefolgt von einer anderen, die die Listenelemente durch Ints ersetzt.
df['column1'] = df['column1'].apply(lambda x:x[1:-1].split(',')).apply(lambda x:[int(i) for i in x])
quelle
Hinzufügen zu Alex ' Antwort. Hier ist eine andere Version, mit der einzelne Elemente von einer Zeichenfolge in eine Liste konvertiert werden können
import pandas as pd from ast import literal_eval df = pd.read_csv("some_csvfile.csv") def item_gen(l): for i in l: yield(i) for i in item_gen(df["some_column_with_list_item"]): print(literal_eval(i))
quelle