【发布时间】:2018-10-17 13:12:05
【问题描述】:
我正在尝试通过收集特定的列对来将数据帧从宽格式转换为长格式,示例如下所示:
数据框示例
df <- data.frame(id=c(1,2,3,4,5), var=c("a","d","g","f","i"),a1=c(3,5,1,2,2), b1=c(2,4,1,2,3), a2=c(8,1,2,5,1), b2=c(1,6,4,7,2), a3=c(7,7,2,3,1), b3=c(1,1,4,9,6))
初始表:
id var a1 b1 a2 b2 a3 b3
1 1 a 3 2 8 1 7 1
2 2 d 5 4 1 6 7 1
3 3 g 1 1 2 4 2 4
4 4 f 2 2 5 7 3 9
5 5 i 2 3 1 2 1 6
想要的结果:
id var a b
1 1 a 3 2
2 1 a 8 1
3 1 a 7 1
4 2 d 5 4
5 2 d 1 6
6 2 d 7 1
7 3 g 1 1
8 3 g 2 4
9 3 g 2 4
10 4 f 2 2
11 4 f 5 7
12 4 f 3 9
13 5 i 2 3
14 5 i 1 2
15 5 i 1 6
条件:
- 应收集 ai 和 bi 对:由于 a 和 b 有 3 对,“a1 和 b1”、“a2 和 b2”和“a3 和 b3”,这些对中的值应移动到一对通过将每条记录复制 3 次来计算“a 和 b”
- 第一个和第二个字段(每个样本的 ID 及其公共变量)应保留在每个复制行中
我认为可以通过 gather() 在 tidyverse 中实现它,但是,据我了解,我认为收集功能可能不适合将此类特定的字段对收集到特定的多列中(两个本例中的列)。
可以让它分别准备三个数据帧并将其绑定到一个(示例脚本如下所示),但是我更喜欢在 tidyverse 中使其在一个连续的管道操作中不停止操作。
df1 <- df %>% dplyr::select(id,var,a1,b1)
df2 <- df %>% dplyr::select(id,var,a2,b2)
df3 <- df %>% dplyr::select(id,var,a3,b3)
df.fin <- bind_rows(df1,df2,df3)
感谢您使用 tidyverse 提出的优雅建议。
=================其他问题==================
@Akrun 和卡米尔 感谢您的建议,并对我迟到的回复感到抱歉。我现在正在尝试将您的想法应用到实际的数据框架中,但仍在努力解决另一个问题。
以下是实际数据框中的列名(对不起,我没有设置每列的任何值,因为这可能无关紧要)。
colnames(df) <- c("hid","mid","rel","age","gen","mlic","vlic",
"wtaz","staz","ocp","ocpot","emp","empot","expm",
"minc","otaz1","op1","dtime1","atime1","dp1","dtaz1",
"pur1", "repm1","lg1t1","lg2t1","lg3t1","lg4t1","expt1",
"otaz2","op2","dtime2","atime2","dp2","dtaz2","pur2",
"repm2","lg1t2","lg2t2","lg3t2","lg4t2","expt2",
"otaz3","op3","dtime3","atime3","dp3","dtaz3","pur3",
"repm3","lg1t3","lg2t3","lg3t3","lg4t3","expt3",
"otaz4","op4","dtime4","atime4","dp4","dtaz4","pur4",
"repm4","lg1t4","lg2t4","lg3t4","lg4t4","expt4",
"otaz5","op5","dtime5","atime5","dp5","dtaz5","pur5",
"repm5","lg1t5","lg2t5","lg3t5","lg4t5","expt5"
)
然后,我正在尝试应用您的建议,如下所示: 在数据框中,1:15 列是公共变量,其他列是重复变量,重复 5 次(1 到 5 位于每个变量的末尾)。我可以运行以下脚本,但仍然有问题:
#### Convert member table into activity table
## Common variables
hm.com <- names(hm)[c(1:15)]
## Repeating variables
hm.rep <- names(hm)[c(-1:-15)]
hm.rename <- unique(sub("\\d+$","",hm.rep))
## Extract members with trips
hm.trip <- hm %>% filter(otaz!=0) %>% data.frame()
## Convert from member into trip table
test <- split(hm.rep, sub(".*[^1-9$]", "", hm.rep)) %>%
map_df(~ hm.trip %>% dplyr::select(hm.com, .x)) %>%
rename_at(16:28, ~ hm.rename) %>%
arrange(hid,mid,dtime,atime) %>%
data.frame()
结果还是有问题:
我可以重命名第一组重复变量,但是从 2 到 5 的剩余字段仍然存在,并且记录未正确存储在数据框中。 我的意思是,一组重复的变量,例如从 otaz2 到 expt2,不是存储在 otaz~expt 的第二行,而是存储在其原始位置(从 otaz2 到 expt2)。我想 map_df 在我的情况下无法正常工作。
========== 问题已解决========== 上面的脚本包含不正确的操作:
错误:
map_df(~ hm.trip %>% dplyr::select(hm.com, .x)) %>%
rename_at(16:28, ~ hm.rename)
正确:
map_df(~ hm.trip %>% dplyr::select(hm.com, .x) %>%
rename_at(16:28, ~ hm.rename))
谢谢,我可以进行下一步了。
【问题讨论】:
标签: r dplyr multiple-columns tidyverse