TL; DR
Ab v0.21
, ist dies ein Fehler, und eine offene Frage auf GitHub. Siehe GH16289.
Warum erhalte ich diesen Fehler?
Dies (aller Wahrscheinlichkeit nach) ist pd.eval
's Fehler, die Serie mit mehr als 100 Zeilen nicht analysieren kann. Hier ist ein Beispiel.
len(s)
300000
pd.eval(s.head(100)) # returns a parsed result
Ange
pd.eval(s.head(101))
AttributeError: 'PandasExprVisitor' object has no attribute 'visit_Ellipsis'
Dieses Problem weiterhin besteht, unabhängig von der Parser oder den Motor.
Was bedeutet dieser Fehler?
Wenn eine Reihe mit mehr als 100 Zeilen übergeben wird, arbeitet pd.eval
auf der __repr__
der Serie, anstatt die darin enthaltenen Objekte (was die Ursache für diesen Fehler ist). Die __repr__
abgeschnittenen Zeilen, ersetzt sie durch eine ...
(Ellipse). Das Auslassungszeichen wird durch den Motor als Ellipsis
Objekt falsch interpretiert -
...
Ellipsis
pd.eval('...')
AttributeError: 'PandasExprVisitor' object has no attribute 'visit_Ellipsis'
Welche genau die Ursache für diesen Fehler ist.
Was kann ich tun, dies zu machen zu arbeiten?
Im Moment gibt es keine Lösung (das Problem ist immer noch ab dem 28.12.2017), aber, es gibt ein paar Problemumgehungen.
Option 1
ast.literal_eval
, wenn Sie, dass Sie alle fehlerhaften Strings haben nicht garantieren können, sollte diese Option aus dem Kasten heraus arbeiten.
Wenn fehlerhafte Daten vorliegen, müssen Sie einen kleinen Fehlercode schreiben. Sie können mit einer Funktion das tun -
def safe_parse(x):
try:
return literal_eval(x)
except (SyntaxError, ValueError):
return np.nan # replace with any suitable placeholder value
Pass diese Funktion apply
-
s.apply(safe_parse)
0 [133, 115, 3, 1]
1 [114, 115, 2, 3]
2 [51, 59, 1, 1]
dtype: object
ast
Werke für eine beliebige Anzahl von Zeilen und ist langsam, aber zuverlässig. Sie können auch pd.json.loads
für JSON-Daten verwenden und die gleichen Ideen wie mit literal_eval
anwenden.
Option 2
yaml.load
Eine weitere große Möglichkeit für einfache Daten Parsen, ich picked this up von @ayhan eine Weile her.
import yaml
s.apply(yaml.load)
0 [133, 115, 3, 1]
1 [114, 115, 2, 3]
2 [51, 59, 1, 1]
dtype: object
Ich habe dies nicht auf komplexere Strukturen getestet, aber das sollte für fast jede grundlegende String-Darstellung von Daten funktionieren.
Sie finden die Dokumentation für PyYAML here. Scrollen Sie ein wenig nach unten und Sie finden weitere Details zur Funktion load
.
Hinweis
- Wenn Sie mit JSON-Daten arbeiten, kann es zweckmäßig sein, die Dateien zu lesen, mit der Verwendung von
pd.read_json
oder pd.io.json.json_normalize
zu beginnen.
Sie auch Parsen durchführen können, wie Sie in Ihren Daten lesen, mit read_csv
-
s = pd.read_csv(converters=literal_eval, squeeze=True)
Wo die converters
Argument, dass die Funktion auf die Säule gegeben gelten, wie es gelesen wird, so dass Sie nicht haben beschäftigen Sie sich später mit dem Parsen.
Fortsetzung der Punkt oben, wenn Sie mit einem Datenrahmen arbeiten, passieren ein dict
-
df = pd.read_csv(converters={'col' : literal_eval})
Wo col
die Spalte, die Sie können auch pd.json.loads
(für JSON-Daten übergeben werden analysiert muss) oder pd.eval
(wenn Sie 100 Zeilen oder weniger haben).
Credits MAXU und Moondra dieses Problem für die Aufdeckung.
ja, ich erinnere mich an diesen Fall ...;) – MaxU
@MaxU Ich stellte sicher, dass Sie und Moondra in der Antwort. Lassen Sie mich wissen, ob ich die Antwort irgendwie verbessern kann! –
Ich mochte auch [@ Ayhans Lösung] (https://Stackoverflow.com/a/45827519/5741205) viel ... – MaxU