R中如何自动将data.frame的逗号分隔字符列转数值并生成长表
R数据框长表转换问题
原始数据格式
;Label;PennElementName;Parameter;EventTime;grupo;item;frases;tags;valores 1;minhasfrases;mouse;Move;1621714127287;A;1;Esse aviso não está vazio e eu preciso clicar logo sobre ele.;timestamps;0, 306, 321, 338, 355, 372, 388, 406, 422, 439, 455, 622, 638, 656, 705, 721, 755, 805, 822, 5189, 5206, 5223, 5238, 5255, 5271, 5288, 5305, 5321, 5338, 5355, 5371, 5388, 5405, 5488, 5505, 5521, 5538, 5555, 5572, 5588, 5605, 5622, 5655 2;minhasfrases;mouse;Move;1621714133140;A;2;Esse aviso está vazio e eu também preciso clicar sobre ele.;timestamps;0, 168, 185, 201, 219, 235, 252, 268, 285, 302, 318, 336, 352, 369, 385, 402, 418, 668, 685, 702, 720, 736, 752, 769, 835, 852, 4652, 4669, 4686, 4702, 4719, 4736, 4752, 4769, 4785, 4802, 4819, 4835, 4852, 4868, 4886, 4902, 4918, 4935, 4952, 4969, 4985, 5002, 5018, 5035 3;minhasfrases;mouse;Move;1621714127287;A;1;Esse aviso não está vazio e eu preciso clicar logo sobre ele.;xpos;864, 865, 878, 892, 896, 896, 891, 882, 882, 882, 882, 882, 879, 878, 877, 876, 875, 874, 873, 875, 897, 940, 972, 1002, 1028, 1048, 1054, 1057, 1061, 1063, 1064, 1067, 1068, 1069, 1070, 1073, 1074, 1077, 1080, 1083, 1084, 1085, 1085 4;minhasfrases;mouse;Move;1621714133140;A;2;Esse aviso está vazio e eu também preciso clicar sobre ele.;xpos;1085, 1085, 1079, 1060, 1039, 1006, 982, 960, 937, 911, 875, 855, 848, 848, 851, 855, 855, 861, 866, 871, 876, 878, 878, 879, 879, 879, 878, 847, 814, 780, 740, 702, 676, 657, 630, 611, 589, 568, 540, 518, 496, 483, 477, 473, 467, 460, 447, 435, 431, 430 5;minhasfrases;mouse;Move;1621714127287;A;1;Esse aviso não está vazio e eu preciso clicar logo sobre ele.;ypos;416, 415, 383, 339, 291, 242, 199, 167, 161, 158, 156, 156, 157, 157, 157, 158, 158, 159, 160, 192, 263, 365, 428, 492, 540, 573, 590, 597, 602, 605, 607, 611, 613, 619, 633, 647, 655, 659, 663, 668, 670, 670, 671 6;minhasfrases;mouse;Move;1621714133140;A;2;Esse aviso está vazio e eu também preciso clicar sobre ele.;ypos;671, 670, 666, 643, 615, 564, 517, 451, 374, 292, 200, 155, 126, 113, 109, 106, 105, 123, 137, 146, 154, 158, 162, 164, 166, 167, 168, 213, 256, 300, 342, 386, 419, 440, 477, 513, 546, 568, 579, 585, 591, 597, 601, 604, 613, 620, 627, 635, 639, 640
需求说明
该数据集列以分号分隔,最后一列valores实际为逗号分隔的字符串,可使用read.csv2()在R中加载数据。需要自动将最后一列转换为数值类型,同时将原表格转为长表格式,不受原数据集行数限制。
现有代码缺陷
现有代码硬编码了6行数据的处理逻辑,通过assign生成固定数量的临时变量,无法适配任意行数的数据集:
# extracting vectors as numeric itens for(k in 1:length(results$valores)){ assign(paste0("obi_", k), as.numeric(unlist(strsplit(results$valores[[k]], split = ", ")))) } # defining same length of vector to cbind them lengths <- max(c(length(obi_1), length(obi_2), length(obi_3), length(obi_4), length(obi_5), length(obi_5))) length(obi_1) <- lengths length(obi_2) <- lengths length(obi_3) <- lengths length(obi_4) <- lengths length(obi_5) <- lengths length(obi_6) <- lengths df <- data.frame(obi_1, obi_2, obi_3, obi_4, obi_5, obi_6) # binding the transpose of the results results <- cbind(results, t(df)) results <- results %>% gather("cols", "values", '1':ncol(results)) %>% select(-c(valores, cols))
目标格式示例
,Label,PennElementName,Parameter,EventTime,grupo,item,frases,tags,values 1,minhasfrases,mouse,Move,1621714127287,A,1,Esse aviso não está vazio e eu preciso clicar logo sobre ele.,timestamps,0 2,minhasfrases,mouse,Move,1621714133140,A,2,Esse aviso está vazio e eu também preciso clicar sobre ele.,timestamps,0 3,minhasfrases,mouse,Move,1621714127287,A,1,Esse aviso não está vazio e eu preciso clicar logo sobre ele.,xpos,864 4,minhasfrases,mouse,Move,1621714133140,A,2,Esse aviso está vazio e eu também preciso clicar sobre ele.,xpos,1085 5,minhasfrases,mouse,Move,1621714127287,A,1,Esse aviso não está vazio e eu preciso clicar logo sobre ele.,ypos,416 6,minhasfrases,mouse,Move,1621714133140,A,2,Esse aviso está vazio e eu também preciso clicar sobre ele.,ypos,671 7,minhasfrases,mouse,Move,1621714127287,A,1,Esse aviso não está vazio e eu preciso clicar logo sobre ele.,timestamps,306 8,minhasfrases,mouse,Move,1621714133140,A,2,Esse aviso está vazio e eu também preciso clicar sobre ele.,timestamps,168 9,minhasfrases,mouse,Move,1621714127287,A,1,Esse aviso não está vazio e eu preciso clicar logo sobre ele.,xpos,865 10,minhasfrases,mouse,Move,1621714133140,A,2,Esse aviso está vazio e eu também preciso clicar sobre ele.,xpos,1085 11,minhasfrases,mouse,Move,1621714127287,A,1,Esse aviso não está vazio e eu preciso clicar logo sobre ele.,ypos,415 12,minhasfrases,mouse,Move,1621714133140,A,2,Esse aviso está vazio e eu também preciso clicar sobre ele.,ypos,670
解决方案
推荐使用tidyr包的separate_rows函数实现需求,代码简洁且自动适配任意行数的数据集:
# 加载依赖包 library(tidyverse) # 读取原始数据 results <- read.csv2("你的数据文件路径.csv", stringsAsFactors = FALSE) # 一步实现拆分+转数值+长表转换 result_long <- results %>% # 按逗号拆分valores列,每个元素单独成一行,其他列值自动复用 separate_rows(valores, sep = ", ") %>% # 将拆分后的valores转为数值类型 mutate(valores = as.numeric(valores)) %>% # 列名重命名为目标格式的values rename(values = valores)
如果需要用基础R实现,也可以通过列表存储拆分结果避免硬编码:
# 读取数据 results <- read.csv2("你的数据文件路径.csv", stringsAsFactors = FALSE) # 拆分valores为数值列表 val_list <- lapply(strsplit(results$valores, ", "), as.numeric) # 计算每个列表元素的长度 val_lengths <- sapply(val_list, length) # 重复原数据行索引,对应每个拆分后的元素 row_idx <- rep(1:nrow(results), val_lengths) # 生成最终长表 result_long <- cbind(results[row_idx, setdiff(colnames(results), "valores")], values = unlist(val_list)) rownames(result_long) <- NULL
两种方法都可以完美适配任意行数的数据集,无需手动调整参数。
内容的提问来源于stack exchange,提问作者Igor de Oliveira Costa
相关产品推荐
相关产品推荐

