在R中按列块拆分数据框并使用rbind合并的实现需求
Got it, let's tackle this reshaping problem where we need to combine columns with shared base names (like a, a1, a2) into single columns while keeping the date values aligned. Here are two reliable approaches:
Method 1: Using tidyr::pivot_longer (Recommended)
This is the cleanest solution using the tidyverse ecosystem, which handles column grouping and renaming automatically.
First, make sure you have the tidyverse installed and loaded:
install.packages("tidyverse") library(tidyverse)
Then run this code (we'll set a random seed so you can reproduce exact values):
set.seed(123) df = data.frame(a = rnorm(4), b = rnorm(4), c = rnorm(4), a1 = rnorm(4), b1 = rnorm(4), c1 = rnorm(4), a2 = rnorm(4), b2 = rnorm(4), c2 = rnorm(4), date = seq(as.Date("2019-05-05"),as.Date("2019-05-08"), 1)) # Reshape to long format long_df <- df %>% pivot_longer( cols = -date, # Leave the date column untouched names_to = c(".value", "group"), # .value keeps the base column name; group stores the suffix names_pattern = "(.)(\\d?)" # Regex to split column names into base (a/b/c) and optional suffix (1/2) ) %>% select(-group) # Remove the temporary group column print(long_df)
How this works:
names_pattern = "(.)(\\d?)"splits each column name into two parts: the first character (a/b/c) and an optional digit (1/2 or empty for original columns)..valuetellspivot_longerto use the first part as the new column names, so alla/a1/a2values stack into a singleacolumn (same logic applies tobandc).
Method 2: Base R Manual Split & Bind
If you prefer not to use tidyverse packages, you can manually split the dataframe into blocks, rename columns, then combine them with rbind:
set.seed(123) df = data.frame(a = rnorm(4), b = rnorm(4), c = rnorm(4), a1 = rnorm(4), b1 = rnorm(4), c1 = rnorm(4), a2 = rnorm(4), b2 = rnorm(4), c2 = rnorm(4), date = seq(as.Date("2019-05-05"),as.Date("2019-05-08"), 1)) # Split into three blocks and rename columns to match block1 <- df[, c("a", "b", "c", "date")] block2 <- df[, c("a1", "b1", "c1", "date")] names(block2) <- c("a", "b", "c", "date") block3 <- df[, c("a2", "b2", "c2", "date")] names(block3) <- c("a", "b", "c", "date") # Combine all blocks long_df <- rbind(block1, block2, block3) print(long_df)
Both methods will produce the 12-row long-format dataframe you're looking for, with a, b, c, and date columns as desired.
内容的提问来源于stack exchange,提问作者Jordan Wrong

