You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R语言中重塑指定结构的data.frame?

Reshape Wide Data Frame to Long Format in R

Hey there! Let's sort out that data reshaping task you've got in R. First, let's start with your original data setup so we're working from the same place:

df <- data.frame(
  custid = c(1,2,3,4),
  prod1 = c('jeans','tshirt','jacket','tshirt'),
  prod1_hnode1 = c(1,2,3,2),
  prod1_hnode2 = c(6,7,8,7),
  prod2 = c('tshirt','jeans','jacket','shirt'),
  prod2_hnode1 = c(2,1,3,4),
  prod2_hnode2 = c(7,6,8,7)
)

Which gives you this wide-format output:

custid prod1 prod1_hnode1 prod1_hnode2 prod2 prod2_hnode1 prod2_hnode2
1      1 jeans            1            6 tshirt            2            7
2      2 tshirt            2            7 jeans            1            6
3      3 jacket            3            8 jacket            3            8
4      4 tshirt            2            7 shirt            4            7

Modern Solution with tidyr::pivot_longer

The cleanest and most intuitive way to get your desired long format is using the pivot_longer function from the tidyr package (part of the popular tidyverse suite). Here's the code that will produce exactly the structure you want:

# Load the tidyverse package (or just tidyr if you prefer)
library(tidyverse)

# Reshape the data
long_df <- df %>%
  pivot_longer(
    cols = -custid,  # Keep custid as our identifier column (doesn't get reshaped)
    names_to = c("prod", ".value"),  # Split column names into two parts: prod label, and value type
    names_pattern = "(prod\\d)(?:_(.*))?"  # Regex to match our column name patterns
  ) %>%
  rename(rec = prod1) %>%  # Rename the product name column to match your desired output
  select(custid, prod, rec, hnode1, hnode2)  # Reorder columns to match your target structure

# Check the result
print(long_df)

Running this will give you:

custid prod  rec    hnode1 hnode2
  <dbl> <chr> <chr>   <dbl>  <dbl>
1      1 prod1 jeans       1      6
2      1 prod2 tshirt      2      7
3      2 prod1 tshirt      2      7
4      2 prod2 jeans       1      6
5      3 prod1 jacket      3      8
6      3 prod2 jacket      3      8
7      4 prod1 tshirt      2      7
8      4 prod2 shirt       4      7

Let's break down what each part does:

  • cols = -custid: We exclude custid from reshaping because we want one row per customer-product pair, keeping custid as the identifier.
  • names_to = c("prod", ".value"): This tells pivot_longer to split each column name into two components:
    • prod: This will hold the prefix like prod1 or prod2.
    • .value: This special keyword means "use this part of the column name as the new column headers" (so hnode1, hnode2, and the product name column).
  • names_pattern = "(prod\\d)(?:_(.*))?": The regex handles two types of column names:
    • For columns like prod1_hnode1: It captures prod1 into the prod group and hnode1 into the .value group (becomes a column header).
    • For columns like prod1: It captures prod1 into the prod group, and the second group is empty—so .value uses prod1 as the column name (which we later rename to rec).
  • rename(rec = prod1): Renames the product name column to match your desired rec header.
  • select(...): Reorders the columns to exactly match the structure you provided.

Alternative: Older Method with reshape2::melt

If you're more comfortable with the older reshape2 package, you can achieve the same result with a bit more cleanup:

library(reshape2)

# First melt the data into a longer format
melted_df <- melt(df, id.vars = "custid")

# Split column names into prod and attribute, then clean up
melted_df <- melted_df %>%
  separate(variable, into = c("prod", "attribute"), sep = "_", fill = "right") %>%
  mutate(attribute = ifelse(is.na(attribute), "rec", attribute)) %>%  # Label product name columns as 'rec'
  pivot_wider(names_from = attribute, values_from = value) %>%  # Pivot back to wide for attributes
  mutate(across(c(hnode1, hnode2), as.numeric)) %>%  # Convert hnode columns back to numeric
  arrange(custid, prod) %>%  # Sort to match target output
  select(custid, prod, rec, hnode1, hnode2)  # Reorder columns

This will also give you the exact structure you want, but pivot_longer is more efficient and straightforward for this type of reshaping.

内容的提问来源于stack exchange,提问作者tushaR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:01:44