如何在R中将宠物年龄字符串(周/月/年)转换为年数值?
Hey there! Let's turn those messy age strings into clean, numeric years using the tidyverse tools you already know—no confusing loops needed. Here's a straightforward approach tailored to your familiarity with mutate() and friends:
Step 1: Load the Tidyverse
First, make sure you've got the package loaded (since you mentioned knowing mutate() and filter(), you probably already do, but just in case):
library(tidyverse)
Step 2: Extract Numeric Values and Units
We'll use stringr functions (part of tidyverse) to pull out the number and the unit from each age string. Then we'll convert the number to numeric format:
pet_adoptions <- pet_adoptions %>% mutate( # Grab the numeric part of the age string age_number = as.numeric(str_extract(age, "\\d+")), # Grab the text unit (like "months" or "years") age_unit = str_extract(age, "[a-zA-Z]+") )
str_extract(age, "\\d+")finds all digits in theagecolumn and pulls them out.str_extract(age, "[a-zA-Z]+")grabs the letters (the unit part) from the string.
Step 3: Convert Units to Years with case_when()
Instead of messy conditional statements, case_when() lets us write clear, readable rules for converting each unit to years. This is perfect for tidy workflows:
pet_adoptions_clean <- pet_adoptions %>% mutate( age_years = case_when( # If the unit includes "year", keep the number as-is str_detect(age_unit, "year") ~ age_number, # Convert months to years (divide by 12) str_detect(age_unit, "month") ~ age_number / 12, # Convert weeks to years (divide by ~52 weeks in a year) str_detect(age_unit, "week") ~ age_number / 52, # Add a rule for days if you have them (divide by 365) str_detect(age_unit, "day") ~ age_number / 365, # For any unrecognized units, return NA (you can adjust this if needed) TRUE ~ NA_real_ ) ) %>% # Optional: Remove the intermediate columns if you don't need them select(-age_number, -age_unit)
str_detect()works likegrepl()—it checks if the unit string contains the keyword (e.g., "year" matches both "year" and "years", which covers plural cases!).case_when()evaluates each condition in order, so make sure your rules are ordered logically.
Example Output
If your original age column looks like this:
| age |
|---|
| 3 months |
| 4 years |
| 3 weeks |
| 14 days |
The final age_years column will be:
| age_years |
|---|
| 0.25 |
| 4.00 |
| ~0.0577 |
| ~0.0384 |
That's it! This approach stays true to the tidyverse style you're comfortable with, and avoids the need for complex loops. If you have other edge cases (like "1 year and 6 months"), we can adjust the code, but this should handle the main cases you mentioned.
内容的提问来源于stack exchange,提问作者Elizabeth Robinson

