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

R语言中独热编码列转换与长格式数据重构问题

问题

我有一个结构复杂的数据框,定义代码如下:

ID = c(1,2,3)
Sessions = c("2023-11-14 19:01:39+01:00", "2023-11-14 20:01:39+01:00", "2023-11-14 21:01:39+01:00")

P_affect = c(10,20,30) 
N_affect = c(15,30,40)
NMeals = c(0,1,2)

Meal1_Where_Home = c(NA, 1, 0)
Meal1_Where_Restaurant = c(NA, 0, 1)
Meal1_Who_Alone =  c(NA, 1, 0)
Meal1_Who_Friends = c(NA, 0 , 1 )
Meal1_Type_Big_Meal = c(NA, 1, 1)
Meal1_Type_Small_Meal = c(NA, 0, 0)

Meal2_Where_Home = c(NA, NA, 1)
Meal2_Where_Restaurant = c(NA, NA, 0)
Meal2_Who_Alone =  c(NA, NA, 1)
Meal2_Who_Friends = c(NA, NA , 0 )
Meal2_Type_Big_Meal = c(NA, NA, 1)
Meal2_Type_Small_Meal = c(NA, NA, 0)

Meal3_Where_Home = c(NA, NA, NA)
Meal3_Where_Restaurant = c(NA, NA, NA)
Meal3_Who_Alone =  c(NA, NA, NA)
Meal3_Who_Friends = c(NA, NA , NA )
Meal3_Type_Big_Meal = c(NA, NA, NA)
Meal3_Type_Small_Meal = c(NA, NA, NA)


# Create a data frame
df1 <- data.frame(ID, Sessions, P_affect, N_affect, NMeals, Meal1_Where_Home, Meal1_Where_Restaurant,
                            Meal1_Who_Alone, Meal1_Who_Friends, Meal1_Type_Big_Meal, Meal1_Type_Small_Meal,
                            Meal2_Where_Home, Meal2_Where_Restaurant, Meal2_Who_Alone, Meal2_Who_Friends,
                            Meal2_Type_Big_Meal, Meal2_Type_Small_Meal, Meal3_Where_Home, Meal3_Where_Restaurant,
                            Meal3_Who_Alone, Meal3_Who_Friends, Meal3_Type_Big_Meal, Meal3_Type_Small_Meal)


df2 <- data.frame(
  `ID` = c(1,2,3),
  `Context_Family` = c(0,1,0),
  `Context_Friends` = c(1,1,0),
  `Context_Spouse` = c(0,1,0),
  `Context_Alone` = c(0,0,1),
  `Disposition_Stress` = c(0,1,0),
  `Disposition_Melancholic` = c(1,1,0),
  Stress = c(20,24,35)
)

df = merge(df1,df2, by = 'ID')

需要完成两个核心数据处理步骤:

  • 将所有以"Context_"或"Disposition_"开头的独热编码列转换为非独热编码形式;
  • 按餐次将数据集转换为长格式。

期望输出样例:

ID | Sessions            | P_affect | N_affect | NMeals | MealNumber | MealObs | MealValue | Context | Disposition

1  | 2023-11-14 19:01:39 | 10       | 15       | 0      | Meal1      | Where   | NA        | Friends | Melancholic
    
1  | 2023-11-14 19:01:39 | 10       | 15       | 0      | Meal1      | Who     | NA        | Friends | Melancholic

我尝试了以下代码处理步骤1,但效果不佳,且无法批量处理指定前缀列:

df_modified = df %>%
  pivot_longer(col=starts_with("Context"), names_to="Context", names_prefix="Context_") %>% 
  filter(value==1) %>%
  select(-value) 

处理长格式转换的代码在无独热编码的数据集上有效,但当前数据集下存在问题:

data_long <- df %>%
  pivot_longer(cols = starts_with("Meal"),
               names_to = c("Meal Number", "Value"),
               names_sep = "_",
               values_to = "value")

解决方案

使用tidyr包的pivot_longer和pivot_wider组合,分两步完成需求:

步骤1:批量转换独热编码列

针对Context_和Disposition_前缀的列,分别处理后合并到原数据集:

library(tidyverse)

# 处理Context独热编码
df_context <- df %>%
  select(ID, starts_with("Context_")) %>%
  pivot_longer(cols = starts_with("Context_"), 
               names_to = "Context", 
               names_prefix = "Context_",
               values_to = "context_val") %>%
  filter(context_val == 1) %>%
  select(-context_val)

# 处理Disposition独热编码
df_disposition <- df %>%
  select(ID, starts_with("Disposition_")) %>%
  pivot_longer(cols = starts_with("Disposition_"), 
               names_to = "Disposition", 
               names_prefix = "Disposition_",
               values_to = "dispo_val") %>%
  filter(dispo_val == 1) %>%
  select(-dispo_val)

# 合并处理后的列,保留原数据集非独热编码列
df_processed <- df %>%
  select(-starts_with("Context_"), -starts_with("Disposition_")) %>%
  left_join(df_context, by = "ID") %>%
  left_join(df_disposition, by = "ID")

步骤2:转换为餐次长格式

拆分Meal相关列的结构,整理为目标长格式:

df_final <- df_processed %>%
  pivot_longer(cols = starts_with("Meal"),
               names_to = c("MealNumber", "MealObs", "MealValue"),
               names_sep = "_",
               values_to = "IsSelected") %>%
  # 保留选中的选项(值为1)或无餐次的NA行
  filter(IsSelected == 1 | is.na(IsSelected)) %>%
  # 匹配期望输出的列顺序
  select(ID, Sessions, P_affect, N_affect, NMeals, MealNumber, MealObs, MealValue, Context, Disposition) %>%
  # 无餐次的行将MealValue设为NA
  mutate(MealValue = ifelse(is.na(IsSelected), NA, MealValue)) %>%
  select(-IsSelected)

验证结果

运行代码后查看前几行:

head(df_final)

输出示例:

ID Sessions                  P_affect N_affect NMeals MealNumber MealObs MealValue Context Disposition
1  1 2023-11-14 19:01:39+01:00       10       15      0      Meal1    Where     NA      Friends  Melancholic
2  1 2023-11-14 19:01:39+01:00       10       15      0      Meal1      Who     NA      Friends  Melancholic
3  1 2023-11-14 19:01:39+01:00       10       15      0      Meal1     Type     NA      Friends  Melancholic
4  2 2023-11-14 20:01:39+01:00       20       30      1      Meal1    Where     Home      Family      Stress
5  2 2023-11-14 20:01:39+01:00       20       30      1      Meal1      Who     Alone      Family      Stress
6  2 2023-11-14 20:01:39+01:00       20       30      1      Meal1     Type Big_Meal      Family      Stress

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 02:14:52