【问题标题】:How to read a data set where variables are stored as rows, and some variable names contain "#"如何读取变量存储为行且某些变量名称包含“#”的数据集
【发布时间】:2016-01-26 09:59:40
【问题描述】:

我有一个相当大的数据集(大约 1200 个变量,每个变量有 14 个观察值),存储在一个文本文件中,具有非常奇怪且绝对不是 tidy 结构。实际上,每个变量都存储为一行,而不是一列,第一行和第二行分别是变量名称和该变量的测量单位。这是一个示例数据集:

Date    --- 1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016
PT-AMB#SRV  V   1.403400    1.403207    1.403265    1.403326    1.403454    1.403783    1.404924    1.404962    1.405291    1.404951    1.404685    1.404812    1.404433    1.404428
PS1-SEC20#SRV   V   2.395769    2.416003    2.362276    2.253045    2.139873    1.939328    2.450442    2.294791    2.085946    1.929666    2.634747    3.067008    3.081949    3.095456

第一个变量称为Date,它是无量纲的(单位---),第二个变量是PT-AMB#SRV,测量单位为伏特V,依此类推。注意:同一行上的两个条目由原始文件中的制表符分隔。一旦我在 Stack Overflow 上复制和粘贴数据,我不确定这是否会被保存。

首先,我尝试读入这样的数据:

df=read.table("TEST.txt",sep="\t")

我收到以下错误:

Error in scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings,  : 
  line 2 did not have 16 elements

如果我手动编辑第二个(和第三个)变量名,将# 更改为-,错误就会消失。

第一个问题是:为什么会发生这种情况,我该如何防止它发生?如果我需要将所有变量名中的所有# 更改为-,我该如何自动执行此操作?最好在R 中,否则命令行很好(我在 Windows 中工作)。

第二个问题:在修改了所有#(这个样本数据集中只有两个)之后,我用

 df=read.table("TEST.txt",sep="\t")

我明白了:

             V1  V2        V3        V4        V5        V6        V7        V8        V9       V10       V11       V12       V13       V14       V15       V16
1          Date --- 1/19/2016 1/19/2016 1/19/2016 1/19/2016 1/19/2016 1/19/2016 1/19/2016 1/19/2016 1/19/2016 1/19/2016 1/19/2016 1/19/2016 1/19/2016 1/19/2016
2    PT-AMB-SRV   V  1.403400  1.403207  1.403265  1.403326  1.403454  1.403783  1.404924  1.404962  1.405291  1.404951  1.404685  1.404812  1.404433  1.404428
3 PS1-SEC20-SRV   V  2.395769  2.416003  2.362276  2.253045  2.139873  1.939328  2.450442  2.294791  2.085946  1.929666  2.634747  3.067008  3.081949  3.095456

然后我尝试转置df,以便变量存储在列中:

df_t=t(df)

我明白了:

    [,1]        [,2]         [,3]           
V1  "Date"      "PT-AMB-SRV" "PS1-SEC20-SRV"
V2  "---"       "V"          "V"            
V3  "1/19/2016" "1.403400"   "2.395769"     
V4  "1/19/2016" "1.403207"   "2.416003"     
V5  "1/19/2016" "1.403265"   "2.362276"     
V6  "1/19/2016" "1.403326"   "2.253045"     
V7  "1/19/2016" "1.403454"   "2.139873"     
V8  "1/19/2016" "1.403783"   "1.939328"     
V9  "1/19/2016" "1.404924"   "2.450442"     
V10 "1/19/2016" "1.404962"   "2.294791"     
V11 "1/19/2016" "1.405291"   "2.085946"     
V12 "1/19/2016" "1.404951"   "1.929666"     
V13 "1/19/2016" "1.404685"   "2.634747"     
V14 "1/19/2016" "1.404812"   "3.067008"     
V15 "1/19/2016" "1.404433"   "3.081949"     
V16 "1/19/2016" "1.404428"   "3.095456" 

不再是数据框,而是字符数组。绝对不是我想要的。我怎样才能使变量存储在列中(整齐的数据集)?我认为问题在于包含测量单位的列,但在转置之前将其删除

df[,"V2"]=NULL   

解决不了任何问题。也许tidyr 可以在这里提供帮助,但我不知道如何。

【问题讨论】:

  • 看看read.table函数(?read.table)中的参数comment.char(默认情况下它是#,所以它后面的所有内容都被认为是注释,因此不会被导入。好消息是,你可以将它定义为你想要的任何东西......)
  • 谢谢! df=read.table("TEST.txt",sep="\t",comment.char="") 解决了第一个问题。第二个呢?我仍然无法转置df 并获得另一个数据帧,其中正确的变量名称和值被正确解释为日期、实数、整数等,具体取决于变量。
  • 正如@Cath 所说的那样,但是为了让您开始尝试转置数字行:df_t <- t(df[,3:1200])。然后手动添加列名:colnames(df_t)<- df[,1]... 然后阅读一下。
  • @StephenHenderson,有数千行,当然我只展示了一些。当然,不仅仅是前两个不是数字的:有很多这样的行,“分散”在数据集中。关于阅读,你到底建议我读什么?我在tidyr 上阅读了 Whickam 的论文:他说变量应该存储在列中,而不是行中,但他没有说明使用哪些命令来解决这个问题。我尝试在谷歌上搜索“r 将变量从行移动到列”。我发现了一些关于使用dcast 的提示并查看了文档条目,但我不明白如何在这里使用它。

标签: r import


【解决方案1】:

将数据读入 DF0,转置并使用type.convert 为列获取适当的类。设置名称并使用适当的格式字符串将第一列转换为"Date" 类。

# replace text = Lines with file = "myfile.dat"
DF0 <- read.table( text = Lines, colClasses = "character", comment = "" )
L <- lapply( as.data.frame( tail( t(DF0), -2 ), stringsAsFactors = FALSE ), type.convert )
DF <- setNames( as.data.frame(L), DF0[[1]] )
DF$Date <- as.Date( DF$Date, format = "%m/%d/%Y" )

结果是:

> DF
         Date PT-AMB#SRV PS1-SEC20#SRV
1  2016-01-19   1.403400      2.395769
2  2016-01-19   1.403207      2.416003
3  2016-01-19   1.403265      2.362276
4  2016-01-19   1.403326      2.253045
5  2016-01-19   1.403454      2.139873
6  2016-01-19   1.403783      1.939328
7  2016-01-19   1.404924      2.450442
8  2016-01-19   1.404962      2.294791
9  2016-01-19   1.405291      2.085946
10 2016-01-19   1.404951      1.929666
11 2016-01-19   1.404685      2.634747
12 2016-01-19   1.404812      3.067008
13 2016-01-19   1.404433      3.081949
14 2016-01-19   1.404428      3.095456

注意:我们使用了这个输入:

Lines <- 
"Date    --- 1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016   1/19/2016
PT-AMB#SRV  V   1.403400    1.403207    1.403265    1.403326    1.403454    1.403783    1.404924    1.404962    1.405291    1.404951    1.404685    1.404812    1.404433    1.404428
PS1-SEC20#SRV   V   2.395769    2.416003    2.362276    2.253045    2.139873    1.939328    2.450442    2.294791    2.085946    1.929666    2.634747    3.067008    3.081949    3.095456"

【讨论】:

  • 伙计,你太棒了!它完美地工作,即使在实际数据集中,除了我用于示例的那些行之外,还有许多其他“讨厌”的行。只需澄清两点:为什么read.table 中需要colClasses?我在read.table帮助中查看了相应的条目,但我不能说我了解很多。另外,我想我得到了第二行的目标,但我不确定as.data.frame( tail( t(DF0), -2 )) 中的-2 的原因是什么。你能解释一下吗?
  • colClasses="character" 让一切变得个性化。当我们转置它时,它将全部被强制转换为一个矩阵,其条目必须全部属于同一类,因此为了安全起见,我们确保它的字符开始。 tail(..., -2) 删除标题和单元。
猜你喜欢
  • 1970-01-01
  • 2013-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多