exibite777
@exibite777
Ведущий системный аналитик

Как в pd.DataFrame комбинировать дату и время из разных столбцов?

Как на примере в этого кода скомбинировать дату и время из разных столбцов?
for SESSION_REPORT_FILE in os.listdir(SESSION_REPORT_PATH):
    start_date=datetime.strptime(SESSION_REPORT_FILE[14:len(SESSION_REPORT_FILE)-4], '%Y-%m-%d')
    fixed_df = pd.read_csv(SESSION_REPORT_PATH + SESSION_REPORT_FILE, sep=';', encoding='utf-8', engine='c', 
            names=['v2m_guid', 'start_time', 'text_length', 'voice_length'], parse_dates=['start_time', 'voice_length'], 
        dtype={'text_length': np.int32}, header=0)
    fixed_df["start_date"]=start_date
    fixed_df['start_time']=datetime.combine(fixed_df["start_date"].date(), fixed_df['start_time'].time())
    fixed_df['voice_length']=datetime.combine(fixed_df["start_date"].date(), fixed_df['voice_length'].time())-fixed_df["start_date"]
    fixed_df['end_time']=fixed_df['start_time']+fixed_df['voice_length']

Падает на строке
datetime.combine(fixed_df["start_date"].date(), fixed_df['start_time'].time())
, что логично, так как я вызываю функции datetime.combine, dateи time, относящиеся к элементам pd.Series к самому pd.Series. Но это казалось логичным, с учетом других кейсов Pandas, где это работает. Подскажите как корректно сделать задуманное, используя методы pd.Series? Использовать цикл совсем не хочетя, иначе теряется магия Pandas

UPDATE
Сделал так
pd.Timestamp.combine(fixed_df["start_date"].dt.date, fixed_df['start_time'].dt.time)
datetime.combine(fixed_df["start_date"].dt.date, fixed_df['start_time'].dt.time)
в обоих случаях получил
TypeError: combine() argument 1 must be datetime.date, not Series
, что наверное тоже логично. Какой аналог функции datetime.combine?
  • Вопрос задан
  • 443 просмотра
Решения вопроса 3
@zexer
Можно попробовать перевести дату и время по отдельности к типу str, затем через пробел сделать конкатенацию, после чего полученное выражение подать на вход функции pd.to_datetime, которая вернет полноценный datetime формат искомых значений.

В случае, если изначальные даты у вас в формате datetime сделать так:
pd.to_datetime(df['start_date'].dt.date.astype(str) + ' ' + df['start_time'].dt.time.astype(str))

А если изначальные даты в строковом формате, то опустить "dt.date" и "dt.time" части.

UPDATE

Еще можно сделать так, например:
date = pd.to_datetime('start_date')
time = pd.to_timedelta('start_time')
date + time
Чтобы получить datetime формат следует сделать следующее:
(date + time).to_pydatetime()
Ответ написан
Комментировать
@o5a
Можно так (если колонка 'start_time' имеет нормальный тип datetime, а не просто строку)
df['new_time'] = df['start_date'].combine(df['start_time'], lambda x,y: datetime.datetime.combine(x, y.time()))
Ответ написан
Комментировать
exibite777
@exibite777 Автор вопроса
Ведущий системный аналитик
Оба решения выше работают, но если обрабатывать таким образом пачку файлу, то производительность pd.read_csv снижается до неприемлемого уровня. В итоге быстрее и проще спрасить обычным способом в список словарей и сконвертить итог в pd.DataFrame, например, так:
SESSION_REPORT=[]
# ЧИТАЕМ ФАЙЛЫ SESSION REPORT В PYTHON-СЛОВАРЬ #
for SESSION_REPORT_FILE in os.listdir(SESSION_REPORT_PATH):
    with open(SESSION_REPORT_PATH+SESSION_REPORT_FILE, "r", newline="",
              encoding="utf-8") as file:
        start_date=datetime.strptime(SESSION_REPORT_FILE[14:len(SESSION_REPORT_FILE)-4], '%Y-%m-%d')
        reader = csv.reader(file, delimiter = ';')
        for line in reader:
            if line[2]=="Длина текста": continue
            start_time=datetime.combine(start_date.date(),
                    datetime.strptime(line[1], '%H:%M:%S').time())
            voice_length=datetime.combine(start_date.date(),
                    datetime.strptime(line[3], '%H:%M:%S').time())-start_date
            SESSION_REPORT.append({"v2m_guid": line[0], "start_date": start_date, 
                "start_time": start_time,
                "voice_length": voice_length,
                "end_time": start_time+voice_length,
                "text_length": int(line[2])})
    # СОЗДАЕМ DATAFRAME PANDAS #
SESSION_REPORT=pd.DataFrame(SESSION_REPORT)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы