dtypes muck mọi thứ lên khi dịch chuyển trên trục một (cột)


9

Hãy xem xét khung dữ liệu df

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

df

   A  B
0  1  X
1  2  Y

Nếu tôi thay đổi axis=0 (mặc định)

df.shift()

     A    B
0  NaN  NaN
1  1.0    X

Nó đẩy tất cả các hàng xuống dưới một hàng như mong đợi.

Nhưng khi tôi thay đổi axis=1

df.shift(axis=1)

    A    B
0 NaN  NaN
1 NaN  NaN

Mọi thứ đều vô giá trị khi tôi mong đợi

     A  B
0  NaN  1
1  NaN  2

Tôi hiểu tại sao điều này xảy ra. Đối với axis=0, Pandas đang vận hành cột theo cột trong đó mỗi cột là một dtypevà khi chuyển đổi, có giao thức rõ ràng về cách xử lý NaNgiá trị được giới thiệu ở đầu hoặc cuối. Nhưng khi chuyển dọc, axis=1chúng tôi giới thiệu sự mơ hồ tiềm năng dtypetừ cột này sang cột khác. Trong trường hợp này, tôi đang cố gắng ép buộc int64vào một objectcột và Pandas quyết định chỉ vô hiệu hóa các giá trị.

Điều này trở nên khó giải quyết hơn khi dtypesint64float64

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

df

   A    B
0  1  1.0
1  2  2.0

Và điều tương tự xảy ra

df.shift(axis=1)

    A   B
0 NaN NaN
1 NaN NaN

Câu hỏi của tôi

Các tùy chọn tốt để tạo một khung dữ liệu được dịch chuyển dọcaxis=1 đó kết quả đã thay đổi giá trị và kiểu chữ là gì?

Đối với int64/ float64trường hợp, kết quả sẽ như sau:

df_shifted

     A  B
0  NaN  1
1  NaN  2

df_shifted.dtypes

A    object
B     int64
dtype: object

Một ví dụ toàn diện hơn

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

Nên như thế này

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

Trông giống như một lỗi với tôi, điều gì xảy ra nếu bạn tạo ra các kiểu chữ của tất cả các cột object?
EdChum

Nó hoạt động. Tôi đã có một vài công việc xung quanh. Tôi chỉ chọc cộng đồng cho một số ý tưởng.
piRSquared

Tôi muốn gửi vấn đề này như một vấn đề, ít nhất họ nên cung cấp một tùy chọn cho quảng cáo dtype cho một loại hỗn hợp nhưobject
EdChum

Tôi sẽ làm điều đó bây giờ.
piRSquared

1
@ EdChum-RebstateMonica Đợi một chút! Sự thay đổi xảy ra hơn blocks>. <Sử dụng thay thế và xemdf = pd.DataFrame(dict(A=[1, 2], B=[3., 4.], C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))
piRSquared

Câu trả lời:


7

Hóa ra Pandas đang chuyển qua các khối tương tự dtypes

Xác định df

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

Nó sẽ chuyển các số nguyên sang cột số nguyên tiếp theo, số float sang cột float tiếp theo và các đối tượng sang cột đối tượng tiếp theo

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

Tôi không biết nếu đó là một ý tưởng tốt, nhưng đó những gì đang xảy ra.


Phương pháp tiếp cận

astype(object) Đầu tiên

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

Se lam được 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

Mặc dù tôi có thể làm điều này

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

4
Đây chắc chắn là một lỗi đối với tôi, điều này làm mất hiệu lực toàn bộ quan điểm về việc có các cột bị khóa và dịch chuyển theo N vị trí cột khôn ngoan
EdChum

1
Tôi sẽ đăng một vấn đề sau cuộc họp của tôi.
piRSquared

Nếu đó là tất cả các strdytpes thì nó hoạt động chính xác, nếu bạn làm tương tự trên df này, df = pd.DataFrame(dict(C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))nó sẽ chuyển 'XY'cột này sang 'F'cột khác, điều này chắc chắn là sai đối với tôi, phiên bản gấu trúc của tôi 0.24.2, nó sẽ dtypequảng bá và không thay đổi các cột trong đó một cách
EdChum


1

Tôi đã thử sử dụng một numpyphương pháp. Phương thức này hoạt động miễn là bạn giữ dữ liệu của mình trong một mảng gọn gàng:

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)

Nhưng khi bạn gọi hàm DataFrametạo, tất cả các cột được chuyển đổi thành objectmặc dù các giá trị trong mảng là 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.