dtypes muck segalanya ketika bergeser pada sumbu satu (kolom)

9

Pertimbangkan kerangka data df

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

df

   A  B
0  1  X
1  2  Y

Jika saya berpindah axis=0(default)

df.shift()

     A    B
0  NaN  NaN
1  1.0    X

Ini mendorong semua baris ke bawah satu baris seperti yang diharapkan.

Tapi saat aku bergeser axis=1

df.shift(axis=1)

    A    B
0 NaN  NaN
1 NaN  NaN

Semuanya nol ketika saya harapkan

     A  B
0  NaN  1
1  NaN  2

Saya mengerti mengapa ini terjadi. Sebab axis=0, Pandas adalah operasi kolom per kolom di mana setiap kolom adalah tunggal dtypedan ketika bergeser, ada protokol yang jelas tentang bagaimana menangani nilai yang diperkenalkan NaNdi awal atau akhir. Tetapi ketika bergeser, axis=1kami memperkenalkan potensi ambiguitas dtypedari satu kolom ke kolom berikutnya. Dalam hal ini, saya mencoba untuk memaksa int64ke dalam objectkolom dan Pandas memutuskan untuk hanya membatalkan nilai.

Ini menjadi lebih bermasalah ketika dtypesada int64danfloat64

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

df

   A    B
0  1  1.0
1  2  2.0

Dan hal yang sama terjadi

df.shift(axis=1)

    A   B
0 NaN NaN
1 NaN NaN

Pertanyaan saya

Apa pilihan yang baik untuk membuat kerangka data yang bergeser axis=1di mana hasilnya telah bergeser nilai dan tipe?

Untuk int64/ float64kasus hasilnya akan terlihat seperti:

df_shifted

     A  B
0  NaN  1
1  NaN  2

dan

df_shifted.dtypes

A    object
B     int64
dtype: object

Contoh yang lebih komprehensif

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

Seharusnya terlihat seperti ini

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
piRquared
sumber
Sepertinya bug bagi saya, apa yang terjadi jika Anda membuat dtypes dari semua kolom object?
EdChum
Berhasil. Saya sudah punya beberapa pekerjaan di sekitar. Saya hanya menyodok komunitas untuk beberapa ide.
piRSquared
Saya akan mengajukan ini sebagai masalah, mereka setidaknya harus menawarkan opsi untuk promosi dtype ke dtype campuran sepertiobject
EdChum
Saya akan melakukannya sekarang.
piRSquared
1
@ EdChum-ReinstateMonica Tunggu sebentar! Pergeseran terjadi lebih dari blocks>. <Gunakan ini sebagai gantinya dan lihatdf = pd.DataFrame(dict(A=[1, 2], B=[3., 4.], C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))
piRSquared

Jawaban:

7

Ternyata Panda bergeser dari blok yang sama dtypes

Tentukan dfsebagai

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

Ini akan menggeser bilangan bulat ke kolom bilangan bulat berikutnya, mengapung ke kolom mengapung berikutnya dan objek ke kolom objek berikutnya

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

Saya tidak tahu apakah itu ide yang baik, tapi itu adalah apa yang terjadi.


Pendekatan

astype(object) pertama

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

Akan berhasil 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

Meskipun saya mungkin akan melakukan ini

pd.DataFrame([
    (np.nan, *t[:-1]) for t in
    df.itertuples(index=False, name=None)
], columns=[*df])
piRquared
sumber
4
Ini jelas merupakan bug bagi saya, ini meniadakan seluruh poin dari memiliki kolom yang dikunci dan bergeser berdasarkan posisi N dalam kolom
EdChum
1
Saya akan memposting masalah setelah pertemuan saya.
piRSquared
Jika itu semua strdytpes, maka itu berfungsi dengan baik, jika Anda melakukan hal yang sama pada dyt ini, df = pd.DataFrame(dict(C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))itu menggeser 'XY'kolom ke 'F'kolom, ini jelas salah bagi saya, versi panda saya adalah 0.24.2, ia harus melakukan dtypepromosi dan tidak menggeser kolom sedemikian rupa. a way
EdChum
Edisi Dibuka
piRSquared
1

Saya mencoba menggunakan numpymetode. Metode ini berfungsi selama Anda menyimpan data dalam array yang numpy:

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)

Tetapi ketika Anda memanggil DataFramekonstructer, semua kolom dikonversi ke objectmeskipun nilai dalam array adalah 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
sumber