2012-08-16 50 views
3

对于看似简单的问题抱歉,但似乎无法找到解决以下重新排列问题的解决方案。我已经习惯使用read.csv来读取带有标题行的文件,但是我有一个带有两个“标题”行的Excel电子表格 - 单元格标识符(a,b,c ... g)以及三组(测量值(X,Y和z;每个1000)对每个小区:将两个标题的csv读入data.frame

a   b  
x y z x y z 
10 1 5 22 1 6 
12 2 6 21 3 5 
12 2 7 11 3 7 
13 1 4 33 2 8 
12 2 5 44 1 9 

CSV文件如下:

a,,,b,, 
x,y,z,x,y,z 
10,1,5,22,1,6 
12,2,6,21,3,5 
12,2,7,11,3,7 
13,1,4,33,2,8 
12,2,5,44,1,9 

我怎样才能在R A data.frame如下所示?

cell x y z 
a 10 1 5 
a 12 2 6 
a 12 2 7 
a 13 1 4 
a 12 2 5 
b 22 1 6 
b 21 3 5 
b 11 3 7 
b 33 2 8 
b 44 1 9 
+3

你会发现,如果你花时间让你的问题可以重现,你会得到更好的答案。请遵循指南(http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example),特别注意关于'dput()'的部分。谢谢! – 2012-08-16 12:28:47

+1

@ AriB.Friedman,'dput()'很好,我一般都很感激,但是如何使用'dput()'来解决'read.csv()'问题呢?在Dropbox上托管CSV可能是另一种选择,但会出现持久性问题。我认为*这个问题 - 即使没有OP的编辑 - 是合理的,尽管对我们其他人来说更多的工作。 – A5C1D2H2I1M1N2O1R2T1 2012-08-16 16:04:14

+0

@mrdwab我在想他可以'输出(read.csv())',因为这不一定是一个read.csv问题,而是一个重新整形后的读入。 – 2012-08-16 17:54:03

回答

6

使用基础R reshape()

temp = read.delim(text="a,,,b,, 
x,y,z,x,y,z 
10,1,5,22,1,6 
12,2,6,21,3,5 
12,2,7,11,3,7 
13,1,4,33,2,8 
12,2,5,44,1,9", header=TRUE, skip=1, sep=",") 
names(temp)[1:3] = paste0(names(temp[1:3]), ".0") 
OUT = reshape(temp, direction="long", ids=rownames(temp), varying=1:ncol(temp)) 
OUT 
#  time x y z id 
# 1.0 0 10 1 5 1 
# 2.0 0 12 2 6 2 
# 3.0 0 12 2 7 3 
# 4.0 0 13 1 4 4 
# 5.0 0 12 2 5 5 
# 1.1 1 22 1 6 1 
# 2.1 1 21 3 5 2 
# 3.1 1 11 3 7 3 
# 4.1 1 33 2 8 4 
# 5.1 1 44 1 9 5 

基本上,你应该只跳过第一行,那里有字母A-G每个第三列。由于子列名全部相同,因此R将在第三列之后的所有列之后自动附加分组编号;所以我们需要为前三列添加一个分组编号。

然后你可以创建一个“id”变量,或者,正如我在这里所做的那样,只需使用这些ID的行名即可。

您可以更改 “时间” 变量设置为 “细胞” 变量,如下所示:

# Change the following to the number of levels you actually have 
OUT$cell = factor(OUT$time, labels=letters[1:2]) 

然后,删除 “时间” 栏:

OUT$time = NULL 

更新

要在下面的评论中回答一个问题,如果第一个标签不是字母,这应该仍然没有问题。我会采取的序列如下:

temp = read.csv("path/to/file.csv", skip=1, stringsAsFactors = FALSE) 
GROUPS = read.csv("path/to/file.csv", header=FALSE, 
        nrows=1, stringsAsFactors = FALSE) 
GROUPS = GROUPS[!is.na(GROUPS)] 
names(temp)[1:3] = paste0(names(temp[1:3]), ".0") 
OUT = reshape(temp, direction="long", ids=rownames(temp), varying=1:ncol(temp)) 
OUT$cell = factor(temp$time, labels=GROUPS) 
OUT$time = NULL 
+0

如果OP有另一个第一个标签而不是一个琐碎的字母怎么办?是否有可能只读第一行? – 2012-08-16 13:41:16

+0

@lselzer,我已添加更新。我不认为这很困难 - 你只需要创建一个只读入第一行并将其用于“单元格”标签的对象。 – A5C1D2H2I1M1N2O1R2T1 2012-08-16 15:58:28

+0

@mrdwab谢谢你的回答。它为我工作得很好。我很高兴这不是一件微不足道的事情。 – user441706 2012-08-17 08:24:22