【问题标题】:How to read factors' levels right in R?如何在 R 中正确读取因子的水平?
【发布时间】:2015-09-23 06:32:18
【问题描述】:

我有一个包含 51993 行和 18 列的大 csv 文件。这是表格的一部分:

head(ddd)
country.of.birth age   sex X2000 X2001 X2002 X2003 X2004 X2005 X2006 X2007
Afghanistan       0    men     0     0     1     2     2     0     1     1
Afghanistan       0  women     1     1     0     0     1     0     0     0
Afghanistan       1    men     0     2     5     2     3     4     1     1
Afghanistan       1  women     4     1     4     2     3     2     3     2
Afghanistan       2    men     5     0     8     7     7     3     5     3
Afghanistan       2  women     4     8     3     9     4     4     4     3

在主 csv 文件中,列是:出生国家、年龄、性别,然后是 2000 年到 2014 年的年份。我的问题是为什么 R 将 X 放在每年的数字之前?

当我使用 str() 函数时,我得到:

> str(ddd)
'data.frame':   15264 obs. of  18 variables:
$ country.of.birth: Factor w/ 261 levels "0","1","10","103",..: 51 51 51 51 51 51 51 51 51 51 ...
$ age             : Factor w/ 38 levels "","0 ","1 ","10 ",..: 2 2 3 3 14 14 17 17 20 20 ...
$ sex             : Factor w/ 39 levels "","0 ","1 ","10 ",..: 38 39 38 39 38 39 38 39 38 39 ...
$ X2000           : Factor w/ 786 levels "","0","1","10",..: 2 3 2 478 555 478 92 4 205 716 ...
$ X2001           : int  0 1 2 1 0 8 11 8 26 19 ...
$ X2002           : int  1 0 5 4 8 3 13 18 22 15 ...
$ X2003           : int  2 0 2 2 7 9 15 13 23 33 ...
$ X2004           : int  2 1 3 3 7 4 11 15 21 22 ...
$ X2005           : int  0 0 4 2 3 4 10 6 13 16 ...
$ X2006           : int  1 0 1 3 5 4 8 13 20 10 ...
$ X2007           : int  1 0 1 2 3 3 6 7 9 17 ...
$ X2008           : int  0 0 2 0 4 5 4 6 8 9 ...
$ X2009           : int  0 1 1 4 7 3 9 10 11 12 ...
$ X2010           : int  1 1 6 4 8 10 17 10 21 16 ...
$ X2011           : int  0 5 9 6 21 18 16 27 34 24 ...
$ X2012           : int  3 5 5 16 30 22 44 48 46 49 ...
$ X2013           : int  3 0 12 19 24 34 54 46 76 71 ...
$ X2014           : int  2 3 15 3 21 29 37 48 64 62 ...

如您所见,性别是一个因素,但有 39 个级别,而它只有两个值(男性)和(女性)。此外,2000 年(表中的 X2000)是一个具有 786 个级别的因子,它应该被读作“int”。为什么 R 读取具有这么多级别的可观察“性别”,为什么它将 2000 年读取为一个因素,而将其他读取为 int(情况如此)?

编辑: 年龄列具有以下形式的值:20-24、25-30、...直到 85-90。另一个类别为 90+

【问题讨论】:

  • 显然,“sex”可以是空白(“”)、0、1、10... 而对于“X2000”,您也可以有空白(“”),即一个字符与整数。
  • 如果需要,请使用 read.csv(..., stringsAsFactors=F) 来避免因子变量。另外我认为在 R 中你不能有一个带有数字名称的列,所以 R 把 X 转换成字符
  • @AndriyTkachenko 你可以。列可以任意命名,甚至是2 + 2。请参阅下面的答案。

标签: r csv


【解决方案1】:

X 放在列名前面,因为 R 不允许列名的第一个字符是数字(试试data.frame(a = 1:10, "3" = runif(10))

年龄是一个因素,因为您有垃圾箱并且您观察到的是预期行为。 R 不将区间作为数字处理,而是作为因子处理。

Sex 变量很奇怪,鉴于当前可用的数据,我会说该变量至少在数据集中的一部分中代表性别以外的东西。数据集是否已拼接在一起?可能是复制/粘贴出错了。请参阅levels(ddd$sex) 以解开所有可能的级别。

【讨论】:

  • 我用 cat 将大文件“缝合”为:cat file2.csv >> file1.csv,然后是cat file3 >> file1,用于我拥有的所有 5 个 csv 文件。我再次检查了文件,我可以在我更正的性别列中看到一些错误。暂时就这些了,谢谢。
  • @FaizLotfy,它们在所有方面都完全相同吗?
  • @FaizLotfy 请检查列中是否有任何变化,以及这是否对应于任何文件。
  • 我做到了。除了内容之外,它们是相同的。生成大文件后,我注意到以下内容: 在年龄列中,“年”一词位于列中的每个数字之后。这造成了失真。我再次生成了大文件,但这次我手动完成了,我复制了每个文件并将其粘贴到我在 LibreOffice 中打开的 csv 文件中的前一个文件下方。在我保存文件之前,我搜索了“年”这个词并将其删除。保存文件后再次打开,发现失真消失了。
  • @FaizLotfy 告诉过你。 :)
【解决方案2】:

read.table 及其相关函数的默认行为是使所有列名在语法上有效。这意味着它们可以在 $ 运算符后不加引号的情况下使用。但是,可以使用check.names = FALSE 参数更改此行为。这将意味着您最终会得到名为 2000 等的列。然后要将这些列与 $ 一起使用,它们需要反引号,例如

ddd$`2000`

如果您想将这些列用于非标准评估,例如

ggplot(ddd, aes(x = sex, y = `2000`)) + geom_boxplot()

对于性别列,必须在更下方的列中有包含数字的条目。检查您的原始 数据。

对于年龄,您的年龄列中有尾随空格。要么在 R 之外删除这些,要么你可以这样做:

ddd$age <- as.numeric(sub(" +$", "", as.character(ddd$age)))

对于 2000 列,从您的 str 输出中不清楚为什么它被视为一个因素。默认情况下,空字符串应被视为 NA,因此不应影响类。你可以试试(假设你现在使用check.names = FALSE):

as.character(ddd$`2000`)[is.na(as.numeric(as.character(ddd$`2000`))) & ddd$`2000` != ""]

这应该打印出列中非空白和非数字的所有元素。这可能又是一个尾随空格问题。

【讨论】:

  • 我试过 check.names=F,它奏效了。我必须使用反引号这一事实使我(现在)坚持使用 X2000 格式。我的其他问题是由原始数据文件中的一些错误引起的(如您所建议的)。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
  • 1970-01-01
相关资源
最近更新 更多