dtypes machen beim Verschieben auf Achse eins (Spalten) Mist.

9

Betrachten Sie den Datenrahmen df

df = pd.DataFrame(dict(A=[1, 2], B=['X', 'Y']))

df

   A  B
0  1  X
1  2  Y

Wenn ich mitschalte axis=0(Standardeinstellung)

df.shift()

     A    B
0  NaN  NaN
1  1.0    X

Es schiebt alle Zeilen wie erwartet um eine Zeile nach unten.

Aber wenn ich mich bewege axis=1

df.shift(axis=1)

    A    B
0 NaN  NaN
1 NaN  NaN

Alles ist null, als ich erwartet hatte

     A  B
0  NaN  1
1  NaN  2

Ich verstehe, warum das passiert ist. Denn axis=0Pandas arbeitet spaltenweise, wobei jede Spalte eine einzelne ist, dtypeund beim Verschieben gibt es ein klares Protokoll, wie mit dem eingeführten NaNWert am Anfang oder Ende umgegangen werden soll. Beim Verschieben führen axis=1wir jedoch eine potenzielle Mehrdeutigkeit dtypevon einer Spalte zur nächsten ein. In diesem Fall versuche ich, int64eine objectSpalte zu erzwingen, und Pandas beschließt, die Werte einfach auf Null zu setzen.

Dies wird problematischer, wenn die dtypessind int64undfloat64

df = pd.DataFrame(dict(A=[1, 2], B=[1., 2.]))

df

   A    B
0  1  1.0
1  2  2.0

Und das gleiche passiert

df.shift(axis=1)

    A   B
0 NaN NaN
1 NaN NaN

Meine Frage

Was sind gute Optionen zum Erstellen eines Datenrahmens, der verschoben wird und axis=1in dem das Ergebnis Werte und d-Typen verschoben hat?

Für den Fall int64/ float64würde das Ergebnis folgendermaßen aussehen:

df_shifted

     A  B
0  NaN  1
1  NaN  2

und

df_shifted.dtypes

A    object
B     int64
dtype: object

Ein umfassenderes Beispiel

df = pd.DataFrame(dict(A=[1, 2], B=[1., 2.], C=['X', 'Y'], D=[4., 5.], E=[4, 5]))

df

   A    B  C    D  E
0  1  1.0  X  4.0  4
1  2  2.0  Y  5.0  5

Sollte so aussehen

df_shifted

     A  B    C  D    E
0  NaN  1  1.0  X  4.0
1  NaN  2  2.0  Y  5.0

df_shifted.dtypes

A     object
B      int64
C    float64
D     object
E    float64
dtype: object
piRSquared
quelle
Sieht für mich wie ein Fehler aus. Was passiert, wenn Sie die d-Typen aller Spalten erstellen object?
EdChum
Es klappt. Ich habe schon ein paar Workarounds. Ich stöbere nur in der Community nach Ideen.
piRSquared
Ich würde dies als Problem einreichen, sie sollten zumindest eine Option für die D-Typ-Werbung für einen gemischten D-Typ wieobject
EdChum
Ich werde das jetzt tun.
piRSquared
1
@ EdChum-ReinstateMonica Warte eine Minute! Die Verschiebung erfolgt über blocks>. <Verwenden Sie diese stattdessen und sehen Siedf = pd.DataFrame(dict(A=[1, 2], B=[3., 4.], C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))
piRSquared

Antworten:

7

Es stellt sich heraus, dass Pandas über ähnliche Blöcke wechseln dtypes

Definieren dfals

df = pd.DataFrame(dict(
    A=[1, 2], B=[3., 4.], C=['X', 'Y'],
    D=[5., 6.], E=[7, 8], F=['W', 'Z']
))

df

#  i    f  o    f  i  o
#  n    l  b    l  n  b
#  t    t  j    t  t  j
#
   A    B  C    D  E  F
0  1  3.0  X  5.0  7  W
1  2  4.0  Y  6.0  8  Z

Die Ganzzahlen werden in die nächste Ganzzahlspalte verschoben, die Gleitkommazahlen in die nächste Gleitkommaspalte und die Objekte in die nächste Objektspalte

df.shift(axis=1)

    A   B    C    D    E  F
0 NaN NaN  NaN  3.0  1.0  X
1 NaN NaN  NaN  4.0  2.0  Y

Ich weiß nicht , ob das eine gute Idee ist, aber das ist , was geschieht.


Nähert sich

astype(object) zuerst

dtypes = df.dtypes.shift(fill_value=object)
df_shifted = df.astype(object).shift(1, axis=1).astype(dtypes)

df_shifted

     A  B    C  D    E  F
0  NaN  1  3.0  X  5.0  7
1  NaN  2  4.0  Y  6.0  8

transpose

Wird es schaffen object

dtypes = df.dtypes.shift(fill_value=object)
df_shifted = df.T.shift().T.astype(dtypes)

df_shifted

     A  B    C  D    E  F
0  NaN  1  3.0  X  5.0  7
1  NaN  2  4.0  Y  6.0  8

itertuples

pd.DataFrame([(np.nan, *t[1:-1]) for t in df.itertuples()], columns=[*df])

     A  B    C  D    E  F
0  NaN  1  3.0  X  5.0  7
1  NaN  2  4.0  Y  6.0  8

Obwohl ich das wahrscheinlich tun würde

pd.DataFrame([
    (np.nan, *t[:-1]) for t in
    df.itertuples(index=False, name=None)
], columns=[*df])
piRSquared
quelle
4
Dies ist definitiv ein Fehler für mich, dies macht den ganzen Punkt ungültig, Spalten
verschlüsselt zu haben
1
Ich werde nach meinem Treffen ein Problem veröffentlichen.
piRSquared
Wenn es nur strDytpes sind, dann funktioniert es richtig. Wenn Sie dasselbe tun, wenn df = pd.DataFrame(dict(C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))es die 'XY'Spalte bis zur 'F'Spalte verschiebt, ist dies definitiv falsch für mich. Meine Pandas-Version ist 0.24.2, es sollte Werbung machen dtypeund die Spalten in solchen nicht verschieben ein Weg
EdChum
Ausgabe eröffnet
piRSquared
1

Ich habe versucht, eine numpyMethode zu verwenden. Die Methode funktioniert so lange, wie Sie Ihre Daten in einem numpy-Array aufbewahren:

def shift_df(data, n):
    shifted = np.roll(data, n)
    shifted[:, :n] = np.NaN

    return shifted

shifted(df, 1)

array([[nan, 1, 1.0, 'X', 4.0],
       [nan, 2, 2.0, 'Y', 5.0]], dtype=object)

Wenn Sie den DataFrameKonstruktor aufrufen , werden alle Spalten konvertiert, objectobwohl die Werte im Array wie folgt lauten float, int, object:

def shift_df(data, n):
    shifted = np.roll(data, n)
    shifted[:, :n] = np.NaN
    shifted = pd.DataFrame(shifted)

    return shifted

print(shift_df(df, 1),'\n')
print(shift_df(df, 1).dtypes)

     0  1  2  3  4
0  NaN  1  1  X  4
1  NaN  2  2  Y  5 

0    object
1    object
2    object
3    object
4    object
dtype: object
Erfan
quelle