在R语言中,将数字作为单个字符读取

3

I have an input file which looks like

222222222224444444444444444477777777777723548464646
233333333224444444444444444477776666667723545864646

当我使用Read table命令将其读入R时,R认为它是一个包含在1列中的单个数字。然而,我需要每个单独字符都有一列。
2 2 2 2 2   2

...

有没有一种方法可以用R来做到这一点?

文件是否只包含一行数字? - jbaums
有多行我编辑了文件..但每一行都应该保持在一行中,只需按描述拆分到列中。 - user3419669
4个回答

3
您可以将其视为固定宽度文件,并使用read.fwf打开,将width参数设置为一个长度与每行字符数(最大值)相同的1向量:
read.fwf("yourFilename", rep(1, chars))

其中yourFilename是您的文件名,chars是每行字符数(在您的示例中为51)。

如果任何行的字符数少于您设置的chars值,则它们将被赋值为NA


我认为这是最好的答案,其他的只是在之后处理数据的技巧。 - PascalVKooten
这意味着该文件是一个固定宽度文件...但没有在任何地方说明? - GWD
没有被提出的具体要求,但这是一个明智的假设,因为该示例应该代表更大的数据集。 - jbaums
每一行都有相同数量的字符,那么我应该在输入文件中给出每一行的长度作为width参数吗? - user3419669
2
此外,对于我(在Ubuntu上的R3.0.2),以上代码将在任何情况下都会给出“NA”作为缺失值。@OP,是的,对于上述示例,您将使用“51”替换“chars”。 - ping
显示剩余5条评论

2

首先,可以使用readLines函数最方便地读取数据。然后,您可以使用strsplit函数将每个字符串(数字序列)轻松分成单个数字。

这里有一个例子(我首先将虚拟数据写入临时文件f):

cat('222222222224444444444444444477777777777723548464646
233333333224444444444444444477776666667723545864646', file=f <- tempfile())
d <- readLines(f)
apply(do.call(rbind, strsplit(d, '')), 2, as.numeric)

最后一行代码首先将文本文件的每一行拆分为单个字符,然后将每个分离的字符串绑定到一个data.frame中(使用do.call(rbind, ...))。最后,我们将其强制转换为数字。如果您希望将对象保留为字符数据,则可以将其保留为do.call(rbind, strsplit(d, ''))
有关更多信息,请参见?strplit

处理数据两次(读取和转换),这并不被建议。 - PascalVKooten
1
@PascalvKooten 我同意 @ping 提供的 read.fwf 更简单,但是关于你复制粘贴的评论,为什么不建议使用呢?我认为你会发现 read.fwf 也使用了 readLines - jbaums
我相信Fortran使用这种设置。Fortran在读取方面也非常快。因此,我认为由于R可以利用Fortran,它可能正在使用类似的方法。另外,还有类似于readChar的东西吧?我很确定这会更慢。 - PascalVKooten
2
非常抱歉,我添加了非常意外的基准测试结果。那个 fwf 看起来实际上非常糟糕(至少在我的设置下,Ubuntu 13.04,R.3.0.1)。 - PascalVKooten
没问题,谢谢你抽出时间来检查它——很好知道。这让我想知道是否还进行了其他相关的检查和平衡,我在这里没有考虑到...... - jbaums
我猜测readLines不会决定任何colClasses或查找注释,因此通过使用colClasses="character"comment.char=""可以改进read.fwf,但这似乎会减慢速度! - ping

2

补充一下非常意外的基准测试结果(对不起,jbaums):

仅针对提供的两行代码:

Unit: microseconds
     expr      min        lq   median        uq      max neval
 jbaums()  265.131  290.2255  307.573  349.1005 1793.644   100
    fwf() 1627.021 1700.5955 1791.578 1986.1865 4910.790   100

对于3000行代码:

Unit: milliseconds
     expr       min        lq    median        uq       max neval
 jbaums()  33.50519  38.47324  41.33132  47.05635  85.21228   100
    fwf() 671.91310 693.56500 707.83914 724.06571 799.11987   100

这实际上意味着你不应该使用固定宽度格式,因为它非常慢。

-1

这样行吗?

unlist(strsplit("123", split=""))

这个例子如果加上一些额外的解释会更好。 - Thom
它会处理数据两次(读取和转换),这是不建议的。 - PascalVKooten
不知道别人怎么做,但我通常会先读取数据,进行分析,然后将其转换为所需的格式和结构,这样做的情况占99%。只有在这个过程稳定之后,我才会合并或跳过读取和/或转换。 - GWD
很抱歉这个例子没有更多的解释,但基本上它本质上就是jbaum建议的(比我早1分钟),只是简化了do.call括号中的工作函数,该函数在每个字符后拆分字符串(split=""可以实现此功能),并将从strsplit()接收到的结果列表进行解列。 - GWD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接