我正试图重新安排R中的数据,如:
Patient ID,Episode Number,Admission Date (A),Admission Date (H),Admission Time (A),Admission Time (H)
1,5,20/08/2011,21/08/2011,1200,1300
2,6,21/08/2011,22/08/2011,1300,1400
3,7,22/08/2011,23/08/2011,1400,1500
4,8,23/08/2011,24/08/2011,1500,1600
转换成:
Record Type,Patient ID,Episode Number,Admission Date,Admission Time
H,1,5,20/08/2011,1200
A,1,5,21/08/2011,1300
H,2,6,21/08/2011,1300
A,2,6,22/08/2011,1400
H,3,7,22/08/2011,1400
A,3,7,23/08/2011,1500
H,4,8,23/08/2011,1500
A,4,8,24/08/2011,1600
(我已经使用了CSV格式,所以更容易使用它们作为测试数据)。
我尝试了重塑()函数,它有点工作:
> reshape(foo, direction = "long", idvar = 1, varying = 3:dim(foo)[2],
> sep = "..", timevar = "dataset")
Patient.ID Episode.Number dataset Admission.Date Admission.Time
1.A. 1 5 A. 20/08/2011 1200
2.A. 2 6 A. 21/08/2011 1300
3.A. 3 7 A. 22/08/2011 1400
4.A. 4 8 A. 23/08/2011 1500
1.H. 1 5 H. 21/08/2011 1300
2.H. 2 6 H. 22/08/2011 1400
3.H. 3 7 H. 23/08/2011 1500
4.H. 4 8 H. 24/08/2011 1600
但它不是我想要的确切格式(我想要每个"患者ID",第一行是"H",第二行是"A")。
此外,当我将其扩展到读取数据(有250多个列)时,它失败了:
> reshape(realdata, direction = "long", idvar = 1, varying =
> 6:dim(foo)[2], sep = "..", timevar = "dataset")
Error in reshapeLong(data, idvar = idvar, timevar = timevar, varying = varying, :
'varying' arguments must be the same length
我想部分原因是颜色看起来像:
> colnames(foo)
[1] "Unique.Key"
[2] "Campus.Code"
[3] "UR"
[4] "Terminal.digit"
[5] "Admission.date..A."
[6] "Admission.date..H."
[7] "Admission.time..A."
[8] "Admission.time..H."
.
.
.
[31] "Medicare.Number"
[32] "Payor"
[33] "Doctor.specialty"
[34] "Clinic"
.
.
.
[202] "Admission.Source..A."
[203] "Admission.Source..H."
。在有后缀的列之间有"公共列"(没有后缀)(希望这有意义)。
从"重塑"(现在是"重塑2")包中使用melt
和cast
(现在是dcast
和家族)的建议不会让您获得您正在寻找的数据形式。特别是,如果你的最终目标是你描述的"半长"格式,你需要做一些额外的处理。
你的问题中有两个问题:
首先是结果的排序。正如@RichieCotton在他的评论和@mac在他的回答中指出的那样,给order()
打电话就足以解决这个问题了。
第二个是错误:
Error in reshapeLong(data, idvar = idvar, timevar = timevar, varying = varying, :
'varying' arguments must be the same length
这是因为,正如您所猜测的,在varying = 6:dim(foo)[2]
选择列表中有不变的列。
解决这个问题的一个简单方法是使用grep
来识别哪些列在变化,并使用它来指定列,而不是像您那样使用(不正确的)catchall。下面是一个工作示例:
set.seed(1)
foo <- data.frame(Unique.Key = 1:4, Campus.Code = LETTERS[1:4],
Admission.Date..A = 11:14, Admission.Date..H = 21:24,
Medicare.Number = letters[1:4], Payor = letters[1:4],
Admission.Source..A = rnorm(4),
Admission.Source..H = rnorm(4))
foo
# Unique.Key Campus.Code Admission.Date..A Admission.Date..H Medicare.Number
# 1 1 A 11 21 a
# 2 2 B 12 22 b
# 3 3 C 13 23 c
# 4 4 D 14 24 d
# Payor Admission.Source..A Admission.Source..H
# 1 a -0.6264538 0.3295078
# 2 b 0.1836433 -0.8204684
# 3 c -0.8356286 0.4874291
# 4 d 1.5952808 0.7383247
找出哪些列是变化的,并将其用作varying
参数:
varyingCols <- grep("\.\.A$|\.\.H$", names(foo))
out <- reshape(foo, direction = "long", idvar = "Unique.Key",
varying = varyingCols, sep = "..")
out[order(out$Unique.Key, rev(out$time)), ]
# Unique.Key Campus.Code Medicare.Number Payor time Admission.Date Admission.Source
# 1.H 1 A a a H 21 0.3295078
# 1.A 1 A a a A 11 -0.6264538
# 2.H 2 B b b H 22 -0.8204684
# 2.A 2 B b b A 12 0.1836433
# 3.H 3 C c c H 23 0.4874291
# 3.A 3 C c c A 13 -0.8356286
# 4.H 4 D d d H 24 0.7383247
# 4.A 4 D d d A 14 1.5952808
如果你的数据很小(没有很多列),你可以手动计算varying
列的位置并指定向量。正如您已经注意到的,idvar
或varying
中未指定的任何列都将被适当地回收。
out <- reshape(foo, direction = "long", idvar = "Unique.Key",
varying = c(3, 4, 7, 8), sep = "..")
您可能能够通过使用熔融和铸造或重塑得到您想要的东西,但您正在寻找非常具体的东西,因此直接进行重塑可能更简单。你可以将原始数据子集分成两个独立的数据帧(一个用于A,一个用于H),然后将它们粘合在一起。
下面的代码在您的样本数据上工作,但我也试图灵活地编写它,以便它有望在您的更大的数据集上工作,只要列与…A一致命名。和. . H。后缀.
#grab the common columns and the "A" columns
#(by using grepl to find any column that doesn't end in ".H.")
foo.a <- foo[,!grepl(x=colnames(foo),pattern = "\.H\.$")]
#strip the "..A." from the end of the ".A." column names
colnames(foo.a) <- sub(x=colnames(foo.a),
pattern="(.*)\.\.A\.$",
rep = "\1")
foo.a$Record.Type <- "A"
#grab the common columns and the "H" columns
#(by using grepl to find any column that doesn't end in ".A.")
foo.h <- foo[,!grepl(x=colnames(foo),pattern = "\.A\.$")]
#strip the "..H." from the end of the "..H." column names
colnames(foo.h) <- sub(x=colnames(foo.h),
pattern="(.*)\.\.H\.$",
rep = "\1")
foo.h$Record.Type <- "H"
#stick them back together
new.foo <- rbind(foo.a,foo.h)
#order by Patient.ID
new.foo <- new.foo[with(new.foo,order(Patient.ID)),]
#re-order the columns as you like
new.foo <- new.foo[,c(1,2,5,3,4)]
这给了我:
> new.foo
Patient.ID Episode.Number Record.Type Admission.Date Admission.Time
1 1 5 A 20/08/2011 1200
5 1 5 H 21/08/2011 1300
2 2 6 A 21/08/2011 1300
6 2 6 H 22/08/2011 1400
3 3 7 A 22/08/2011 1400
7 3 7 H 23/08/2011 1500
4 4 8 A 23/08/2011 1500
8 4 8 H 24/08/2011 1600