#python #pandas #datetime
#python #pandas #дата-время
Вопрос:
Я хотел бы создать столбец в фрейме данных, который был бы результатом двух других
В приведенном ниже примере были созданы два фрейма данных: df1 и df2.
Затем был создан третий фрейм данных, который является соединением первых двух. В этом df3 столбец «Даты» был изменен на тип DateTime.
После этого был создан столбец «DateMonth», месяц которого был извлечен из столбца «Даты».
import pandas as pd
import numpy as np
from datetime import datetime
# df1 and df2:
id_sales = [1, 2, 3, 4, 5, 6]
col_names = ['Id', 'parrotId', 'Dates']
df1 = pd.DataFrame(columns = col_names)
df1.Id = id_sales
df1.parrotId = [1, 2, 3, 1, 2, 3]
df1.Dates = ['1900-01-01', '2012-08-20', '1900-01-01', '1900-01-01', '2016-02-21', '2012-08-21']
col_names2 = ['parrotId', 'months']
df2 = pd.DataFrame(columns = col_names2)
df2.parrotId = [1, 2, 3]
df2.months = [('Mar,Jun,Sept,Dec'), ('Mar,Jun,Sept,Dec'), ('Mar,Jun,Sept,Dec')]
df3 = pd.merge(df1, df2, on = 'parrotId')
df3.Dates = pd.to_datetime(df3['Dates'], format = "%Y-%m-%d")
С помощью пользователя Lukas была создана следующая функция
def matched(row):
if type(row['months'])==str:
# for the case ('Feb, Mar, Apr') - get numerical representation of month from your string and return True if the 'Dates' value matches with some list item
return row['Dates'].month in [datetime.strptime(mon.strip()[:3], '%b').month for mon in row['months'].split(',')]
else:
# for numbers - return True if months match
return row['Dates'].month==row['months']
Применение:
df3['DateMonth'] = df3.apply(matched, axis=1).astype(int)
В приведенном выше примере у меня не было проблем. Но при репликации в моем наборе данных я получил следующее сообщение об ошибке:
Ошибка значения: (‘остаются неконвертированные данные: t’, ‘произошло с индексом 16772’)
Даты столбца — это имя типа: Date, dtype: datetime64[ns]
Индекс 16772:
months Mar,Jun,Sept,Dec
Dates 2015-07-31 00:00:00
Индекс 16771:
months Jan,Apr,Jul,Oct
Dates 2013-01-01 00:00:00
Уникальными значениями являются:
array([0, 'Jan,Apr,Jul,Oct', 'Feb,May,Aug,Nov', 'Mar,Jun,Sept,Dec'],
dtype=object)
Как устранить эту ошибку?
Комментарии:
1. Есть ли случайно «Sept» в ваших данных где-нибудь там, где должно быть «Sep»?
2. Пожалуйста, приведите мне пример того, как проверить это в фрейме данных
3. Извините, я не знаю, как обращаться с фреймами данных, но единственный способ, которым ошибка имеет смысл, — это если вы попытались
datetime.strptime()
вызвать строку, состоящую из допустимого трехбуквенного названия месяца плюс дополнительное «t». (Редактировать: в ошибке также упоминается индекс 16772. Это может помочь вам найти это.)4. Как выглядят данные с индексом 16772? Ваш MCVE отлично работает на моей стороне.
5. @glibdud указывает на ошибку. Поместите
df2.months = [12, ('Febt, Mar, Mar'), 0]
в свой MCVE.
Ответ №1:
Неверны входные данные.
Убедитесь, что datetime.strptime()
получены правильные входные данные. Например, strptime
%b
требуется месяц из трех букв.
В match()
уберите пробел из разделения и сократите результат до трех символов.
return row['Dates'].month in [datetime.strptime(mon.strip()[:3], '%b').month for mon in row['months'].split(',')]
Рабочий пример
import pandas as pd
import numpy as np
from datetime import datetime
# df1 and df2:
id_sales = [1, 2, 3, 4, 5, 6]
col_names = ['Id', 'parrotId', 'Dates']
df1 = pd.DataFrame(columns = col_names)
df1.Id = id_sales
df1.parrotId = [1, 2, 3, 1, 2, 3]
df1.Dates = ['2012-12-25', '2012-08-20', '2013-07-23', '2014-01-14', '2016-02-21', '2015-10-31']
col_names2 = ['parrotId', 'months']
df2 = pd.DataFrame(columns = col_names2)
df2.parrotId = [1, 2, 3]
df2.months = [12, ('Febt,Mar,Mar'), 0]
df3 = pd.merge(df1, df2, on = 'parrotId')
df3.Dates = pd.to_datetime(df3['Dates'], format = "%Y-%m-%d")
# determine if df3['Dates'].month is zero or one offset (is one)
#print(df3['Dates'].apply(lambda x: x.month))
#exit(0)
def matched(row):
#print("Will process row", row)
if type(row['months'])==str:
# for the case ('Feb, Mar, Apr') - get numerical representation of month from your string and return True if the 'Dates' value matches with some list item
print (row['Dates'].month)
# determine if datetime.strptime is zero or one offset (is one)
# print ([datetime.strptime(mon.strip()[:3], '%b').month for mon in row['months'].split(',')])
return row['Dates'].month in [datetime.strptime(mon.strip()[:3], '%b').month for mon in row['months'].split(',')]
else:
# for numbers - return True if months match
return row['Dates'].month==row['months']
df3['DateMonth'] = df3.apply(matched, axis=1).astype(int)
datetime.strptime('Mar'[:4], '%b').month
print (df3)
Комментарии:
1. Я изменил функцию с помощью предложенного кода. Ошибка не возвращена, но результаты были противоречивыми. Для одних и тех же значений были присвоены разные результаты. Например, дата 1900-01-01 и месяцы март, июнь, сентябрь, декабрь; иногда возвращается 0, а иногда возвращается 1.
2. Обновите свой код в Q, чтобы другие пользователи могли сосредоточиться на семантической ошибке now.
3. Хорошо. Я уже делал это, и это иллюстрируется индексом, который выдал ошибку, и индексом, который не выдал ошибку. Однако результаты теперь противоречивы. Я действительно не понимаю, почему.
4. Я вижу,
mon.strip(), '%b'
и неmon.strip()[:3], '%b'
в вашем примере выше. На моей стороне, похоже, это работает, но не содержит всех входных данных.5. Если у вас это работает, пожалуйста, примите ответ. Если нет, возможно, вы сможете пролить некоторый свет на то, в чем заключается несоответствие.