Столбец Datetime приводится к int при установке с помощью .loc и slice - PullRequest
3 голосов
/ 05 июня 2019

У меня есть столбец datetime, и мне нужно изменить некоторые из этих значений на новые datetime.Когда я устанавливаю значения с помощью df.loc [indices, 'col'] = new_datetimes, незатронутые значения приводятся к int, в то время как новые установленные значения находятся в datetime.Если я устанавливаю значения по одному, приведения типа не происходит.

Для иллюстрации я создал образец df только с одним столбцом.

df = pd.DataFrame([dt.datetime(2019,1,1)]*5)
df.loc[[1,3,4]] = [dt.datetime(2019,1,2)]*3
df

Это приводит к следующему: вывод

Если я изменяю индексы 1,3,4 индивидуально:

df = pd.DataFrame([dt.datetime(2019,1,1)]*5)
df.loc[1] = dt.datetime(2019,1,2)
df.loc[3] = dt.datetime(2019,1,2)
df.loc[4] = dt.datetime(2019,1,2)
df

Я получаю правильный вывод: вывод

Aперед установкой было предложено превратить список в пустой массив, что решает проблему.Однако, если вы попытаетесь установить несколько столбцов (некоторые из которых не являются датами и временем) с использованием массива numpy, проблема снова возникнет.

В этом примере в фрейме данных есть два столбца, и я пытаюсь установить оба столбца.

df = pd.DataFrame({'dt':[dt.datetime(2019,1,1)]*5, 'value':[1,1,1,1,1]})
df.loc[[1,3,4]] = np.array([[dt.datetime(2019,1,2)]*3, [2,2,2]]).T
df

Это дает следующий вывод: вывод

Может кто-нибудь объяснить, что является причиной принуждения и как его предотвратить?Код, который я написал, который использует это, был написан более месяца назад и работал нормально, может ли это быть одним из тех предупреждений о том, что в будущих версиях панд не будут функционировать определенные функции?

Объяснение того, что происходит, будет с благодарностью, потому что я написал другой код, который, вероятно, использует аналогичную функциональность, хочет убедиться, что все работает как задумано.

Ответы [ 2 ]

2 голосов
/ 05 июня 2019

Решение, предложенное w-m , имеет такую ​​«неловкую деталь», что столбец результата также имеет часть времени (его не было раньше).

У меня также есть такое замечание, что DataFrames - это таблицы , а не Series , поэтому у них есть столбцы, каждый со своим именем, и это плохая привычка полагаться на имена столбцов по умолчанию (последовательные номера).

Итак, я предлагаю другое решение, затрагивающее обе вышеупомянутые проблемы:

Для создания исходного DataFrame я выполнил:

df = pd.DataFrame([dt.datetime(2019, 1, 1)]*5, columns=['c1'])

Обратите внимание, что я указал имя для единственного столбца.

Затем я создал другой DataFrame:

df2 = pd.DataFrame([dt.datetime(2019,1,2)]*3, columns=['c1'], index=[1,3,4])

Содержит ваши «новые» даты и цифры, которые вы использовали в loc Я установил в качестве index (снова с тем же именем столбца).

Затем, чтобы обновить df , используйте (что неудивительно) df.update :

df.update(df2)

Эта функция выполняет обновление на месте, поэтому, если вы напечатаете (df) , вы получите:

          c1
0 2019-01-01
1 2019-01-02
2 2019-01-01
3 2019-01-02
4 2019-01-02

Как видите, под индексами 1, 3 и 4 у вас новые даты и нет временной части , как и прежде.

1 голос
/ 05 июня 2019

[dt.datetime(2019,1,2)]*3 - список объектов Python.Этот конкретный список содержит только datetime, но Pandas, похоже, не распознает это и обрабатывает его как есть - список объектов любого типа.

Если вы преобразуете его в типизированный массив, тогда Pandasсохранит исходный тип столбца d в ​​неизменном виде:

df.loc[[1,3,4]] = np.asarray([dt.datetime(2019,1,2)]*3)

Надеюсь, этот обходной путь поможет вам, но вы все равно можете сообщить об ошибке в Pandas.У меня нет объяснения, почему объекты datetime должны быть приведены к целым числам в первом примере вывода.

...