如何使用transpose函数(t)将21个受试者的小时(0-23)数据转置为行?
解决受试者小时数据转置问题
嘿,我来帮你搞定这个数据转置的需求!你的目标是把504行(21个受试者×24小时)的小时数据转换成21行、每行24列(对应0-23小时)的dataframe,之前的嵌套循环代码因为索引逻辑和初始化的问题没得到预期结果,我给你几个简洁靠谱的解决方案,顺便说说原来代码的问题出在哪。
先梳理原始数据
你的原始数据是data_temps_All1,结构是504行的data.table/data.frame,只有一列hour,按顺序每个受试者的0-23小时各占一行(也就是前24行是受试者1的小时,接下来24行是受试者2的,以此类推)。首先我们需要给每个数据行标记对应的受试者ID,这是后续转置的关键。
方法1:Base R 快速实现(最简洁)
利用矩阵的特性直接转换,代码非常短:
# 把hour列转成24行的矩阵,然后转置,再转成dataframe result_df <- as.data.frame(t(matrix(data_temps_All1$hour, nrow = 24))) # 给列命名为0-23 colnames(result_df) <- 0:23
原理:matrix(data_temps_All1$hour, nrow=24)会把504个小时数据按列填充成24行21列的矩阵,转置后就变成21行24列,正好对应每个受试者一行,每行24个小时值。
方法2:Tidyverse 风格(更易读,适合复杂数据处理)
如果你习惯用dplyr和tidyr,可以用宽表转换的方式:
library(tidyverse) result_df <- data_temps_All1 %>% # 添加受试者ID:每个ID重复24次,共21个ID mutate(subject_id = rep(1:21, each = 24)) %>% # 把hour列转成宽格式,列名用小时值 pivot_wider(names_from = hour, values_from = hour) %>% # 移除subject_id列(如果不需要的话) select(-subject_id)
这样得到的结果同样是21行,列名就是0-23,每行对应一个受试者的小时数据。
方法3:Data.table 高效实现(适合大数据)
因为你的原始数据是data.table,用data.table的dcast函数效率更高:
library(data.table) # 先给data.table添加受试者ID data_temps_All1[, subject_id := rep(1:21, each = 24)] # 转置成宽表 result_df <- dcast(data_temps_All1, subject_id ~ hour, value.var = "hour") # 移除subject_id列(可选) result_df[, subject_id := NULL]
说说你原来代码的问题
你之前的循环逻辑有几个明显的问题:
- 初始化错误:
test=data.frame(1:24,t(0:23))创建的是24行2列的dataframe,teste=data.frame(1:21,t(0:23))是21行2列的,和需要的24列结构完全不符; - 循环索引冗余:
for循环会自动帮你递增i和j,手动写j=j+1和i=i+1反而会打乱循环逻辑; - 赋值逻辑错误:
teste[i,]= test[j,]的时候,循环到最后j会变成25,超出了test的行数(只有24行),导致赋值出错。
用上面的方法都能轻松得到你想要的21行、每行0-23的dataframe,选你习惯的方式就行!
内容的提问来源于stack exchange,提问作者Emmanuel GNOFAM
相关产品推荐
相关产品推荐

