按id从宽到长收集列
Gathering columns from wide to long by id
我有这样一个数据框:
set.seed(100)
drugs <- data.frame(id = 1:5,
drug_1 = letters[1:5], drug_dos_1 = sample(100,5),
drug_2 = letters[3:7], drug_dos_2 = sample(100,5)
)
id drug_1 drug_dos_1 drug_2 drug_dos_2
1 a 31 c 49
2 b 26 d 81
3 c 55 e 37
4 d 6 f 54
5 e 45 g 17
我想把这个乱七八糟的 table 变成一个整洁的 table,所有药物的 id 都在一栏中,相应的药物剂量在一栏中。 table 最后应该是这样的:
id drug dosage
1 a 31
1 c 49
2 b 26
2 d 81
etc
我想这可以通过使用将数据从宽格式转换为长格式的重塑功能来实现,但我没有做到。
一个选项是 data.table
中的 melt
,它可以在 measure
参数中采用多个 patterns
library(data.table)
melt(setDT(drugs), measure = patterns('^drug_\d+$', 'dos'),
value.name = c('drug', 'dosage'))[, variable := NULL][order(id)]
# id drug dosage
#1: 1 a 31
#2: 1 c 49
#3: 2 b 26
#4: 2 d 81
#5: 3 c 55
#6: 3 e 37
#7: 4 d 6
#8: 4 f 54
#9: 5 e 45
#10 5 g 17
在这里,'drug'在所有列中都是通用的,所以我们需要创建一个独特的模式。一种方法是指定起始位置 (^
),后跟 'drug' 子字符串,然后是下划线 (_
) 和最后的一个或多个数字 (\d+
) ( $
) 的字符串。对于 'dos',只需使用该子字符串来匹配那些具有 'dos'
的列名称
library(dplyr)
drugs %>% gather(key,val,-id) %>% mutate(key=gsub('_\d','',key)) %>% #replace _1 and _2 at the end wiht nothing
mutate(key=gsub('drug_','',key)) %>% group_by(key) %>% #replace drug_ at the start of dos with nothin and gruop by key
mutate(row=row_number()) %>% spread(key,val) %>%
select(id,drug,dos,-row)
# A tibble: 10 x 3
id drug dos
<int> <chr> <chr>
1 1 a 31
2 1 c 49
3 2 b 26
4 2 d 81
5 3 c 55
6 3 e 37
7 4 d 6
8 4 f 54
9 5 e 45
10 5 g 17
Warning message:
attributes are not identical across measure variables;
they will be dropped
#This warning generated as we merged drug(chr) and dose(num) into one column (val)
我有这样一个数据框:
set.seed(100)
drugs <- data.frame(id = 1:5,
drug_1 = letters[1:5], drug_dos_1 = sample(100,5),
drug_2 = letters[3:7], drug_dos_2 = sample(100,5)
)
id drug_1 drug_dos_1 drug_2 drug_dos_2
1 a 31 c 49
2 b 26 d 81
3 c 55 e 37
4 d 6 f 54
5 e 45 g 17
我想把这个乱七八糟的 table 变成一个整洁的 table,所有药物的 id 都在一栏中,相应的药物剂量在一栏中。 table 最后应该是这样的:
id drug dosage
1 a 31
1 c 49
2 b 26
2 d 81
etc
我想这可以通过使用将数据从宽格式转换为长格式的重塑功能来实现,但我没有做到。
一个选项是 data.table
中的 melt
,它可以在 measure
参数中采用多个 patterns
library(data.table)
melt(setDT(drugs), measure = patterns('^drug_\d+$', 'dos'),
value.name = c('drug', 'dosage'))[, variable := NULL][order(id)]
# id drug dosage
#1: 1 a 31
#2: 1 c 49
#3: 2 b 26
#4: 2 d 81
#5: 3 c 55
#6: 3 e 37
#7: 4 d 6
#8: 4 f 54
#9: 5 e 45
#10 5 g 17
在这里,'drug'在所有列中都是通用的,所以我们需要创建一个独特的模式。一种方法是指定起始位置 (^
),后跟 'drug' 子字符串,然后是下划线 (_
) 和最后的一个或多个数字 (\d+
) ( $
) 的字符串。对于 'dos',只需使用该子字符串来匹配那些具有 'dos'
library(dplyr)
drugs %>% gather(key,val,-id) %>% mutate(key=gsub('_\d','',key)) %>% #replace _1 and _2 at the end wiht nothing
mutate(key=gsub('drug_','',key)) %>% group_by(key) %>% #replace drug_ at the start of dos with nothin and gruop by key
mutate(row=row_number()) %>% spread(key,val) %>%
select(id,drug,dos,-row)
# A tibble: 10 x 3
id drug dos
<int> <chr> <chr>
1 1 a 31
2 1 c 49
3 2 b 26
4 2 d 81
5 3 c 55
6 3 e 37
7 4 d 6
8 4 f 54
9 5 e 45
10 5 g 17
Warning message:
attributes are not identical across measure variables;
they will be dropped
#This warning generated as we merged drug(chr) and dose(num) into one column (val)