wake-up-neo.net

Bestimmen des Pandas-Spalten-Datentyps

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:

  • Gibt es eine Möglichkeit, Pandas zu zwingen, auf die Datentypen der Eingabedaten zu schließen?
  • Wenn nicht, gibt es eine Möglichkeit, nachdem die Daten geladen wurden, um die Datentypen irgendwie abzuleiten?

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? 

11
code base 5000

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)})
15
lmo

Sie können die Objekte auch nach dem Löschen irrelevanter Elemente mit infer_objects() ableiten. Unten ist ein allgemeines Beispiel.

df_orig = pd.DataFrame({"A": ["a", 1, 2, 3], "B": ["b", 1.2, 1.8, 1.8]})
df = df_orig.iloc[1:].infer_objects()
print(df_orig.dtypes, df.dtypes, sep='\n\n')

Ausgabe:

 output print

1
shahar_m

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
0
MisterMonk