dtypes придушує речі при зміщенні на першу вісь (стовпці)


9

Розглянемо фрейм даних df

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

df

   A  B
0  1  X
1  2  Y

Якщо я зміщуся axis=0(за замовчуванням)

df.shift()

     A    B
0  NaN  NaN
1  1.0    X

Це натискає всі рядки вниз на один ряд, як очікувалося.

Але коли я зміщуся axis=1

df.shift(axis=1)

    A    B
0 NaN  NaN
1 NaN  NaN

Все недійсне, коли я очікував

     A  B
0  NaN  1
1  NaN  2

Я розумію, чому це сталося. Бо axis=0Pandas працює стовпцем за стовпцями, де кожен стовпець є єдиним, dtypeі при зміщенні є чіткий протокол про те, як поводитися з введеним NaNзначенням на початку або в кінці. Але при зміщенні вздовж axis=1ми вводимо потенційну неоднозначність dtypeвід однієї колонки до другої. У цьому випадку я намагаюся насильницько перейти int64у objectстовпчик, і Pandas вирішує просто обнулити значення.

Це стає більш проблематичним , коли dtypesє int64іfloat64

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

df

   A    B
0  1  1.0
1  2  2.0

І відбувається те саме

df.shift(axis=1)

    A   B
0 NaN NaN
1 NaN NaN

Моє запитання

Які хороші варіанти створення фрейму даних, який зміщений уздовж, axis=1в якому результат змістив значення та типи?

Для int64/ float64випадку результат виглядатиме так:

df_shifted

     A  B
0  NaN  1
1  NaN  2

і

df_shifted.dtypes

A    object
B     int64
dtype: object

Більш вичерпний приклад

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

Має виглядати так

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

Мені схоже на помилку, що трапиться, якщо скласти типи всіх стовпців object?
EdChum

Це працює. У мене вже є декілька робіт навколо. Я просто тикаю громаді на деякі ідеї.
піRSquared

Я б подав це як проблему, вони, принаймні, повинні запропонувати варіант просування dtype для змішаного типу, наприклад,object
EdChum

Я зараз це зроблю.
piRSquared

1
@ EdChum-ReinstateMonica Почекай хвилинку! Зрушення відбувається над blocks>. <Використовуйте це замість і дивітьсяdf = pd.DataFrame(dict(A=[1, 2], B=[3., 4.], C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))
piRSquared

Відповіді:


7

Виявляється, Панда переходить на блоки подібних dtypes

Визначте 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

Він перемістить цілі числа до наступного цілого стовпця, плавці - до наступного стовпця з плаваючою, а об'єкти - до наступного стовпця об'єкта

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

Я не знаю, чи це гарна ідея, але це те, що відбувається.


Підходи

astype(object) спочатку

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

Зробимо 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

Хоча я б, мабуть, зробив це

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

4
Це, безумовно, помилка для мене, це приводить до недійсності всієї точки клавіш стовпців і зміщення на N позицій по стовпцям
EdChum

1
Я опублікую випуск після своєї зустрічі.
піRSquared

Якщо це все strdytpes, то воно працює правильно, якщо ви робите те саме на цьому df, df = pd.DataFrame(dict(C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))він зміщує 'XY'стовпчик аж до 'F'стовпця, це для мене, безумовно, неправильно. Моя версія панди - 0.24.2це повинно робити dtypeпросування, а не зміщувати стовпці в таких a way
EdChum


1

Я спробував використовувати 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)

Але коли ви викликаєте DataFrameконструктор, усі стовпці перетворюються в objectхоча значення в масиві 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.