基于条件转换DataFrame时间字段为24小时制及错误解决
Let's tackle your problem step by step. First, let's recap your scenario: you have a pandas DataFrame with 12-hour time strings (NewFirst, NewLast as object type) and corresponding hour values (FirstNumberHour, LastNumberHour as float64). You want to convert these to 24-hour format (add 12 when the string contains "p"), then combine the resulting hours with a date column to create datetime objects.
The Error You Encountered
Your initial code threw a TypeError: can only concatenate str (not "float") to str — this likely stemmed from an accidental string concatenation typo (maybe in how you defined or referenced variables). But regardless, there are cleaner, more reliable ways to achieve your goal.
Solution 1: List Comprehension for Offset Calculation
This approach uses list comprehensions to generate 12-hour offsets for entries containing "p", then adds those offsets to your existing hour columns:
import pandas as pd import numpy as np # Sample DataFrame matching your input DF = pd.DataFrame({ 'ID': [1,2,3], 'FirstNumberHour': [7.0,2.0,4.0], 'NewFirst': ['7a','2a','4p'], 'LastNumberHour': [4.0,10.0,11.0], 'NewLast': ['4p','10p','11p'] }) # Calculate offset and update FirstNumberHour DF["FirstOffset"] = [12 if "p" in item else 0 for item in DF["NewFirst"].astype(str)] DF["FirstNumberHourUpdate"] = DF["FirstNumberHour"].astype(int) + DF["FirstOffset"] # Calculate offset and update LastNumberHour DF["LastOffset"] = [12 if "p" in item else 0 for item in DF["NewLast"].astype(str)] DF["LastNumberHourUpdate"] = DF["LastNumberHour"].astype(int) + DF["LastOffset"] # Optional: Clean up temporary offset columns DF = DF.drop(["FirstOffset", "LastOffset"], axis=1)
This produces your desired output:
| ID | FirstNumberHour | NewFirst | LastNumberHour | NewLast | FirstNumberHourUpdate | LastNumberHourUpdate |
|---|---|---|---|---|---|---|
| 1 | 7.0 | 7a | 4.0 | 4p | 7 | 16 |
| 2 | 2.0 | 2a | 10.0 | 10p | 2 | 22 |
| 3 | 4.0 | 4p | 11.0 | 11p | 16 | 23 |
Solution 2: Use pd.to_datetime (Simpler, More Robust)
Instead of manual offset calculations, you can directly parse the NewFirst/NewLast strings to 24-hour hours using pandas' datetime tools. Note we use %I (for 12-hour format hours) instead of %H (24-hour format):
# Generate 24-hour hours directly from the time strings DF["FirstNumberHourUpdate"] = pd.to_datetime(DF["NewFirst"], format="%I%p").dt.hour DF["LastNumberHourUpdate"] = pd.to_datetime(DF["NewLast"], format="%I%p").dt.hour
This method automatically handles edge cases like 12a/12p and requires fewer lines of code.
Combine with Date Column to Create Datetime Objects
Assuming you have a date column (e.g., Date with values like 2024-01-01), here are two ways to merge dates with your 24-hour hours:
Method A: String Concatenation + pd.to_datetime
# Add sample date column for demonstration DF["Date"] = "2024-01-01" # Combine date and original time string to create full datetime DF["FirstDatetime"] = pd.to_datetime(DF["Date"] + " " + DF["NewFirst"], format="%Y-%m-%d %I%p") DF["LastDatetime"] = pd.to_datetime(DF["Date"] + " " + DF["NewLast"], format="%Y-%m-%d %I%p")
Method B: dt.combine with datetime.time
If you want to use the updated 24-hour hours directly:
from datetime import time # Convert date column to datetime type first DF["Date"] = pd.to_datetime(DF["Date"]) # Merge date with time objects created from updated hours DF["FirstDatetime"] = DF.apply(lambda row: row["Date"].combine(time(row["FirstNumberHourUpdate"])), axis=1) DF["LastDatetime"] = DF.apply(lambda row: row["Date"].combine(time(row["LastNumberHourUpdate"])), axis=1)
Key Notes
- You don't need to convert
NewFirst/NewLastto float to check for "p" — just ensure they're treated as strings (use.astype(str)if needed) to avoid errors with missing values. - The
pd.to_datetimemethod is more robust than manual calculations, as it handles edge cases and formatting inconsistencies automatically.
内容的提问来源于stack exchange,提问作者Raven

