基于另一数据框按列名(日期)替换R语言数据框中指定内容的实现方法
Got it, let's work through this problem step by step. Using tidyverse tools (which you're already leveraging with data_frame) makes this straightforward. Here's how to get your desired output:
Step 1: Load Required Packages
First, make sure you have the tidyverse installed and loaded—this includes tibble, dplyr, and tidyr which we'll use for reshaping and manipulating data:
library(tidyverse)
Step 2: Define Your Original Data Frames
Just to confirm, here's the code for your original datasets (as you provided):
# Create df name <- c("luis", "John", "Leo") `2022-08-01` <- c(NA,"yes","yes") `2022-08-02` <- c("yes",NA,"yes") `2022-08-03` <- c(NA,"yes",NA) df <- data_frame(name, `2022-08-01`, `2022-08-02`, `2022-08-03`) # Create df2 date <- c("2022-08-01", "2022-08-02", "2022-08-03") value <- c("a,b","a,c","d") df2 <- data_frame(date, value)
Step 3: Reshape and Merge Data
We'll first convert df to a "long" format so we can easily match dates with df2, then join the two datasets:
# Convert df to long format df_long <- df %>% pivot_longer(cols = -name, names_to = "date", values_to = "status") # Merge with df2 to get matching values for each date df_merged <- df_long %>% left_join(df2, by = "date")
Step 4: Replace "yes" with Corresponding Values
Use case_when to replace any "yes" entries with the matching value from df2, while keeping NA values intact:
df_merged <- df_merged %>% mutate(new_value = case_when( status == "yes" ~ value, TRUE ~ status # Preserve NA or other existing values ))
Step 5: Reshape Back to Wide Format and Rename Dates
Convert the data back to wide format, and reformat the date column names to dd/mm/yy:
df_final <- df_merged %>% # Convert date string to Date type, then reformat to dd/mm/yy mutate(date = format(as.Date(date), "%d/%m/%y")) %>% # Reshape back to wide format pivot_wider(names_from = date, values_from = new_value) %>% # Ensure the name column stays first select(name, everything())
Step 6: View the Final Result
If you run df_final, you'll get exactly the output you wanted:
df_final #> # A tibble: 3 × 4 #> name `01/08/22` `02/08/22` `03/08/22` #> <chr> <chr> <chr> <chr> #> 1 luis NA a,c NA #> 2 John a,b NA d #> 3 Leo a,b a,c NA
Key Notes:
- Using
pivot_longerandpivot_widermakes it easy to handle column-based date data—this is the "tidy data" approach, which simplifies matching and replacement tasks. - The
format(as.Date(date), "%d/%m/%y")line safely converts the date strings to the desired format, avoiding any manual string manipulation errors. case_whengives you clear, readable control over which values get replaced.
内容的提问来源于stack exchange,提问作者Johan

