So json_normalize eine Spalte mit NaNs
Sep 13 2020
- Diese Frage ist spezifisch für Datenspalten in a
pandas.DataFrame - Diese Frage hängt davon ab , ob die Werte in den Spalten sind
str,dictoderlistTyp. - Diese Frage befasst sich mit dem Umgang mit den
NaNWerten, wenn diesdf.dropna().reset_index(drop=True)keine gültige Option ist.
Fall 1
- Bei einer Spalte vom
strTyp müssen die Werte in der Spalte vor der Verwendung indicttype konvertiertast.literal_evalwerden.json_normalize.
import numpy as np
import pandas as pd
from ast import literal_eval
df = pd.DataFrame({'col_str': ['{"a": "46", "b": "3", "c": "12"}', '{"b": "2", "c": "7"}', '{"c": "11"}', np.NaN]})
col_str
0 {"a": "46", "b": "3", "c": "12"}
1 {"b": "2", "c": "7"}
2 {"c": "11"}
3 NaN
type(df.iloc[0, 0])
[out]: str
df.col_str.apply(literal_eval)
Error:
df.col_str.apply(literal_eval) results in ValueError: malformed node or string: nan
Fall 2
dictVerwenden Siepandas.json_normalizebei einer Spalte vom Typ, um Schlüssel in Spaltenüberschriften und Werte in Zeilen zu konvertieren
df = pd.DataFrame({'col_dict': [{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}, {"c": "11"}, np.NaN]})
col_dict
0 {'a': '46', 'b': '3', 'c': '12'}
1 {'b': '2', 'c': '7'}
2 {'c': '11'}
3 NaN
type(df.iloc[0, 0])
[out]: dict
pd.json_normalize(df.col_dict)
Error:
pd.json_normalize(df.col_dict) results in AttributeError: 'float' object has no attribute 'items'
Fall 3
- In einer Typenspalte
strmit derdictInnenseite alist. - So normalisieren Sie die Spalte
- anwenden
literal_eval, da explodieren nicht fürstrTyp funktioniert - Explodieren Sie die Spalte, um die
dictszu trennenden Zeilen zu trennen - Normalisieren Sie die Spalte
- anwenden
df = pd.DataFrame({'col_str': ['[{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}]', '[{"b": "2", "c": "7"}, {"c": "11"}]', np.nan]})
col_str
0 [{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}]
1 [{"b": "2", "c": "7"}, {"c": "11"}]
2 NaN
type(df.iloc[0, 0])
[out]: str
df.col_str.apply(literal_eval)
Error:
df.col_str.apply(literal_eval) results in ValueError: malformed node or string: nan
Antworten
2 TrentonMcKinney Sep 13 2020 at 23:59
- Wie in einem Kommentar erwähnt, besteht immer die Möglichkeit:
df = df.dropna().reset_index(drop=True)- Das ist in Ordnung für die Dummy-Daten hier oder wenn es sich um einen Datenrahmen handelt, bei dem die anderen Spalten keine Rolle spielen.
- Keine gute Option für Datenrahmen mit zusätzlichen Spalten, die erforderlich sind.
Fall 1
- Da die Spalte
strTypen enthält , füllen Sie mit'{}'(astr)
import numpy as np
import pandas as pd
from ast import literal_eval
df = pd.DataFrame({'col_str': ['{"a": "46", "b": "3", "c": "12"}', '{"b": "2", "c": "7"}', '{"c": "11"}', np.NaN]})
col_str
0 {"a": "46", "b": "3", "c": "12"}
1 {"b": "2", "c": "7"}
2 {"c": "11"}
3 NaN
type(df.iloc[0, 0])
[out]: str
# fillna
df.col_str = df.col_str.fillna('{}')
# convert the column to dicts
df.col_str = df.col_str.apply(literal_eval)
# use json_normalize
df = df.join(pd.json_normalize(df.col_str)).drop(columns=['col_str'])
# display(df)
a b c
0 46 3 12
1 NaN 2 7
2 NaN NaN 11
3 NaN NaN NaN
Fall 2
- Da die Spalte
dictTypen enthält , füllen Sie mit{}(nicht astr) - Dies muss mit einem Diktatverständnis ausgefüllt werden, da
fillna({})dies nicht funktioniert
df = pd.DataFrame({'col_dict': [{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}, {"c": "11"}, np.NaN]})
col_dict
0 {'a': '46', 'b': '3', 'c': '12'}
1 {'b': '2', 'c': '7'}
2 {'c': '11'}
3 NaN
type(df.iloc[0, 0])
[out]: dict
# fillna
df.col_dict = df.col_dict.fillna({i: {} for i in df.index})
# use json_normalize
df = df.join(pd.json_normalize(df.col_dict)).drop(columns=['col_dict'])
# display(df)
a b c
0 46 3 12
1 NaN 2 7
2 NaN NaN 11
3 NaN NaN NaN
Fall 3
- Füllen Sie das
NaNsmit'[]'(astr) - Jetzt
literal_evalwird es funktionieren .explodekann für die Spalte verwendet werden, um diedictWerte in Zeilen zu trennen- Jetzt muss die
NaNsNotwendigkeit erfüllt werden mit{}(nicht astr) - Dann kann die Spalte normalisiert werden
- Für den Fall, dass die Spalte
listsvondictsist, die nicht vomstrTyp sind, fahren Sie mit fort.explode.
df = pd.DataFrame({'col_str': ['[{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}]', '[{"b": "2", "c": "7"}, {"c": "11"}]', np.nan]})
col_str
0 [{"a": "46", "b": "3", "c": "12"}, {"b": "2", "c": "7"}]
1 [{"b": "2", "c": "7"}, {"c": "11"}]
2 NaN
type(df.iloc[0, 0])
[out]: str
# fillna
df.col_str = df.col_str.fillna('[]')
# literal_eval
df.col_str = df.col_str.apply(literal_eval)
# explode
df = df.explode('col_str').reset_index(drop=True)
# fillna again
df.col_str = df.col_str.fillna({i: {} for i in df.index})
# use json_normalize
df = df.join(pd.json_normalize(df.col_str)).drop(columns=['col_str'])
# display(df)
a b c
0 46 3 12
1 NaN 2 7
2 NaN 2 7
3 NaN NaN 11
4 NaN NaN NaN