Wenn Daten in Pandas Dataframe importiert werden, werden sie manchmal als object
importiert. Dies ist in Ordnung und gut für die meisten Operationen, aber ich versuche, eine benutzerdefinierte Exportfunktion zu erstellen, und meine Frage lautet:
Ich weiß, ich kann Pandas sagen, dass dies vom Typ int, str usw. ist. Aber ich möchte das nicht tun. Ich hatte gehofft, Pandas könnten klug genug sein, um alle Datentypen zu kennen, wenn ein Benutzer eine Spalte importiert oder hinzufügt .
EDIT - Beispiel für den Import
a = ['a']
col = ['somename']
df = pd.DataFrame(a, columns=col)
print(df.dtypes)
>>> somename object
dtype: object
Der Typ sollte string sein?
Dies ist nur eine Teilantwort, aber Sie können die Häufigkeit des Datentyps der Elemente in einer Variablen über den gesamten DataFrame wie folgt ermitteln:
dtypeCount =[df.iloc[:,i].apply(type).value_counts() for i in range(df.shape[1])]
Das kehrt zurück
dtypeCount
[<class 'numpy.int32'> 4
Name: a, dtype: int64,
<class 'int'> 2
<class 'str'> 2
Name: b, dtype: int64,
<class 'numpy.int32'> 4
Name: c, dtype: int64]
Es wird nicht gut gedruckt, aber Sie können Informationen für jede Variable nach Standort abrufen:
dtypeCount[1]
<class 'int'> 2
<class 'str'> 2
Name: b, dtype: int64
damit sollten Sie herausfinden, welche Datentypen das Problem verursachen und wie viele davon vorhanden sind.
Sie können dann die Zeilen mit einem str-Objekt in der zweiten Variablen überprüfen
df[df.iloc[:,1].map(lambda x: type(x) == str)]
a b c
1 1 n 4
3 3 g 6
Daten
df = DataFrame({'a': range(4),
'b': [6, 'n', 7, 'g'],
'c': range(3, 7)})
Hier ein (nicht perfekter) Versuch, einen besseren Inferer zu schreiben. Wenn Sie bereits Daten in Ihrem Datenrahmen haben, wird der Inferer den kleinsten möglichen Typ erraten. Datetime fehlt momentan, aber ich denke, es könnte ein Ausgangspunkt sein. Mit diesem Inferer kann ich 70% des Speichers in Verwendung bringen.
def infer_df(df, hard_mode=False, float_to_int=False, mf=None):
ret = {}
# ToDo: How much does auto convertion cost
# set multiplication factor
mf = 1 if hard_mode else 0.5
# set supported datatyp
integers = ['int8', 'int16', 'int32', 'int64']
floats = ['float16', 'float32', 'float64']
# ToDo: Unsigned Integer
# generate borders for each datatype
b_integers = [(np.iinfo(i).min, np.iinfo(i).max, i) for i in integers]
b_floats = [(np.finfo(f).min, np.finfo(f).max, f) for f in floats]
for c in df.columns:
_type = df[c].dtype
# if a column is set to float, but could be int
if float_to_int and np.issubdtype(_type, np.floating):
if np.sum(np.remainder(df[c], 1)) == 0:
df[c] = df[c].astype('int64')
_type = df[c].dtype
# convert type of column to smallest possible
if np.issubdtype(_type, np.integer) or np.issubdtype(_type, np.floating):
borders = b_integers if np.issubdtype(_type, np.integer) else b_floats
_min = df[c].min()
_max = df[c].max()
for b in borders:
if b[0] * mf < _min and _max < b[1] * mf:
ret[c] = b[2]
break
if _type == 'object' and len(df[c].unique()) / len(df) < 0.1:
ret[c] = 'category'
return ret