【问题标题】:R mistreat a number as a characterR将数字视为字符
【发布时间】:2013-12-13 21:43:27
【问题描述】:

我正在尝试将一系列文本文件读入 R。这些文件具有相同的格式,至少看起来是相同的格式。一切都很好,除了一个文件。当我阅读该文件时,R 将所有数字视为字符。我用 as.numeric 转换回来,但数据值改变了。我还尝试将文本文件转换为 csv,然后读入 R,但它也不起作用。请问有人遇到过这样的问题吗?请问怎么修?谢谢!

数据来自人类死亡率数据库。由于版权问题,我无法在此处附加数据。但每个人都可以通过 HMD 注册并下载数据(www.mortality.org)。例如,我使用了澳大利亚和比利时的 1 比 1 曝光数据。

我的代码如下:

AUSe<-read.table("AUS.Exposures_1x1.txt",skip=1,header=TRUE)[,-5]
BELe<-read.table("BEL.Exposures_1x1.txt",skip=1,header=TRUE)[,-5]

然后我想在上面的数据框或矩阵中添加一些行。这适用于澳大利亚数据(例如,AUSe[1,3]+AUSe[2,3])。但是将相同的命令应用于比利时数据时发生错误:BELe[1, 3] + BELe[2, 3] 中的错误:二进制运算符的非数字参数。但是,如果您查看文本文件,就会知道这是两个数字。很明显,R在读取文本文件的时候把数字当做字符处理,比较奇怪。

【问题讨论】:

  • read.csv( ..., stringsAsFactors=FALSE) (编辑:这与@josilber 的评论相吻合)
  • 您要转换为 csv 的文本文件中有什么内容?它是如何不起作用的?请发布您遇到的问题以及您尝试过的示例。
  • 正如暗示的那样,您很可能在列中有一些字符。这将导致 R 最初将其存储为因子。当在一个因子上使用 as.numeric 时,您不会获得原始数字 - 您将获得因子水平。给定的答案将允许您将其作为字符读取 - 此时您应该检查数据以查看哪些值不是“实际数字”。

标签: r


【解决方案1】:

试试这个:

BELe<-read.table("BEL.Exposures_1x1.txt",skip=1, colClasses="numeric", header=TRUE)[,-5]

或者您当然可以只发布该文件的一小部分,并且至少在我的管辖范围内不会违反任何版权法(我认为这与人类死亡率数据库相同)。

Belgium, Exposure to risk (period 1x1)     Last modified: 04-Feb-2011, MPv5 (May07)

   Year      Age       Female          Male         Total
   1841        0        61006.15     62948.23    123954.38 
   1841        1        55072.53     56064.21    111136.73 
   1841        2        51480.76     52521.70    104002.46 
   1841        3        48750.57     49506.71     98257.28 
   ....         .        ....

所以我可能会建议更准确的 colClasses:

BELe<-read.table("BEL.Exposures_1x1.txt",skip=2,  #  really two lines to skip I think
                 colClasses=c(rep("integer", 2), rep("numeric",3)),
                 header=TRUE)[,-5]

我怀疑问题的发生是因为以下几行:

   1842      110+           0.00         0.00         0.00 

因此,您需要确定您对保留110+ 值有多大兴趣。使用我的方法,他们将被强制转换为NA's。 (好吧,我以为他们会这样,但和你一样,我遇到了一个错误。所以需要这个多步骤过程:

 BELe<-read.table("Exposures_1x1.txt",skip=2,
                  header=TRUE)
 BELe[ , 2:5] <- lapply(BELe[ , 2:5], as.character)
 str(BELe)
#-------------
'data.frame':   18759 obs. of  5 variables:
 $ Year  : int  1841 1841 1841 1841 1841 1841 1841 1841 1841 1841 ...
 $ Age   : chr  "0" "1" "2" "3" ...
 $ Female: chr  "61006.15" "55072.53" "51480.76" "48750.57" ...
 $ Male  : chr  "62948.23" "56064.21" "52521.70" "49506.71" ...
 $ Total : chr  "123954.38" "111136.73" "104002.46" "98257.28" ...
#-------------
 BELe[ , 2:5] <- lapply(BELe[ , 2:5], as.numeric)

#----------
Warning messages:
1: In lapply(BELe[, 2:5], as.numeric) : NAs introduced by coercion
2: In lapply(BELe[, 2:5], as.numeric) : NAs introduced by coercion
3: In lapply(BELe[, 2:5], as.numeric) : NAs introduced by coercion
4: In lapply(BELe[, 2:5], as.numeric) : NAs introduced by coercion
str(BELe)
#-----------
'data.frame':   18759 obs. of  5 variables:
 $ Year  : int  1841 1841 1841 1841 1841 1841 1841 1841 1841 1841 ...
 $ Age   : num  0 1 2 3 4 5 6 7 8 9 ...
 $ Female: num  61006 55073 51481 48751 47014 ...
 $ Male  : num  62948 56064 52522 49507 47862 ...
 $ Total : num  123954 111137 104002 98257 94876 ...
# and just to show that tey are not really integers:
 BELe$Total[1:5]
#[1] 123954.38 111136.73 104002.46  98257.28  94875.89

【讨论】:

  • 感谢您的回复。但我仍然有一个问题。第二列中的一个条目是“110+”,这会导致错误。因此,我将 colClasses 更改为整数、字符和 3 个数字。现在我收到以下错误:扫描错误(文件,什么,nmax,sep,dec,引用,跳过,nlines,na.strings,:scan()期望'a real',得到'。'
  • 此外,我真的看不出 AUS 和 BEL 数据之间的区别。请问为什么 R 会以不同的方式对待它们?
  • 很奇怪。我虽然我的 colClasses 方法会强制转换为“数字”。不知道为什么没有。发布测试解决方案:
  • 再次感谢您。我仍然认为应该有一种更简单的方法来处理这个问题。
  • 嗯,我认为有一个简单的方法。 colClasses 过去肯定有一种方法,这当然是我阅读手册的方式。我认为read.table 中引入了一个错误。
【解决方案2】:

我通常阅读这些文件的方式是:

BELexp <- read.table("BEL.Exposures_1x1.txt", skip = 2, header = TRUE, na.strings = ".", as.is = TRUE)

请注意,比利时在第一次世界大战中丢失了 3 年可能永远无法恢复的数据,因此这三年都是 NA,在这些文件中标有字符串"."。因此参数na.strings = "."。由于"110+",指定该参数将处理除Age 之外的所有列,这是字符(有意)。 HMD 这样做的原因是用户必须有意识地对待开放年龄组。您可以使用以下方法将年龄列转换为整数:

BELexp$Age <- as.integer(gsub("[+]", "", BELexp$Age))

由于此类问题长期以来一直是 R-HMD 用户的祸根,因此 HMD 最近在 github 上的一个小但不断增长的包中发布了一些 R 函数,称为(目前)DemogBerkeley。函数readHMD() 消除了上述所有令人头疼的问题:

library(devtools)
install_github("DemogBerkeley", subdir = "DemogBerkeley", username = "UCBdemography")

BELexp <- readHMD("BEL.Exposures_1x1.txt")

请注意,添加了一个名为OpenInterval 的新指标列,同时将 Age 转换为如上所述的整数。

【讨论】:

    【解决方案3】:

    你可以试试 read.csv(... stringsAsFactors=FALSE) 吗?

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-26
    • 2015-06-28
    • 2016-03-05
    • 1970-01-01
    • 2019-05-01
    • 1970-01-01
    • 2017-04-29
    相关资源
    最近更新 更多