为啥在读取数据框时我的列名中出现 X.?

Posted

技术标签:

【中文标题】为啥在读取数据框时我的列名中出现 X.?【英文标题】:Why am I getting X. in my column names when reading a data frame?为什么在读取数据框时我的列名中出现 X.? 【发布时间】:2012-05-13 13:28:57 【问题描述】:

我问了question about this a few months back,我认为答案已经解决了我的问题,但我又遇到了问题,解决方案对我不起作用。

我正在导入 CSV:

orders <- read.csv("<file_location>", sep=",", header=T, check.names = FALSE)

这是数据框的结构:

str(orders)

'data.frame':   3331575 obs. of  2 variables:
 $ OrderID  : num  -2034590217 -2034590216 -2031892773 -2031892767 -2021008573 ...
 $ OrderDate: Factor w/ 402 levels "2010-10-01","2010-10-04",..: 263 263 269 268 301 300 300 300 300 300 ...

如果我在第一列 OrderID 上运行 length 命令,我会得到:

length(orders$OrderID)
[1] 0

如果我在 OrderDate 上运行 length,它会正确返回:

length(orders$OrderDate)
[1] 3331575

这是headCSV 的复制/粘贴。

OrderID,OrderDate
-2034590217,2011-10-14
-2034590216,2011-10-14
-2031892773,2011-10-24
-2031892767,2011-10-21
-2021008573,2011-12-08
-2021008572,2011-12-07
-2021008571,2011-12-07
-2021008570,2011-12-07
-2021008569,2011-12-07

现在,如果我重新运行read.csv,但去掉check.names 选项,dataframe 的第一列现在在名称的开头有一个 X。

orders2 <- read.csv("<file_location>", sep=",", header=T)

str(orders2)

'data.frame':   3331575 obs. of  2 variables:
 $ X.OrderID: num  -2034590217 -2034590216 -2031892773 -2031892767 -2021008573 ...
 $ OrderDate: Factor w/ 402 levels "2010-10-01","2010-10-04",..: 263 263 269 268 301 300 300 300 300 300 ...

length(orders$X.OrderID)
[1] 3331575

这可以正常工作。

我的问题是为什么R 在第一列名称的开头添加一个 X.?从 CSV 文件中可以看出,没有特殊字符。它应该是一个简单的负载。添加check.names 虽然会从 CSV 导入名称,但会导致数据无法正确加载,我无法对其执行分析。

我能做些什么来解决这个问题?

旁注:我意识到这是一个小问题 - 我认为我加载正确但没有得到我预期的结果这一事实让我更加沮丧。我可以使用colnames(orders)[1] &lt;- "OrderID" 重命名该列,但仍然想知道为什么它不能正确加载。

【问题讨论】:

您能否剪切并粘贴以下输出:head(orders) & head(orders2) 我更想看到实际的原始 csv 文件。你能把它贴在某个地方并提供一个链接,这样我们就可以下载它并尝试重现这种行为。不管问题是什么,我的猜测是答案在于文件的精确结构和内容。 我没有收到订单的 str,但随后收到了 length(orders$OrderID) [1]0 我和@joran 在一起;我想在文件的开头有一个不可见的字符被拉入列名(check.names=FALSE)或触发名称更改(check.names=TRUE)。不幸的是,CSV 的剪辑和过去可能不会显示这一点。 dput(names(orders)[1]) 给了什么?另外,如果length(orders[[1]]) 给出了正确的值,那么您就知道它在名称中。 【参考方案1】:

read.csv() 是更通用的read.table() 函数的封装。后一个函数的参数check.names 记录为:

check.names: logical.  If ‘TRUE’ then the names of the variables in the
         data frame are checked to ensure that they are syntactically
         valid variable names.  If necessary they are adjusted (by
         ‘make.names’) so that they are, and also to ensure that there
         are no duplicates.

如果您的标头包含语法无效的标签,则make.names() 将根据无效名称将其替换为有效名称,删除无效字符并可能在X 前面添加:

R> make.names("$Foo")
[1] "X.Foo"

这记录在?make.names:

Details:

    A syntactically valid name consists of letters, numbers and the
    dot or underline characters and starts with a letter or the dot
    not followed by a number.  Names such as ‘".2way"’ are not valid,
    and neither are the reserved words.

    The definition of a _letter_ depends on the current locale, but
    only ASCII digits are considered to be digits.

    The character ‘"X"’ is prepended if necessary.  All invalid
    characters are translated to ‘"."’.  A missing value is translated
    to ‘"NA"’.  Names which match R keywords have a dot appended to
    them.  Duplicated values are altered by ‘make.unique’.

您看到的行为与read.table() 加载数据的记录方式完全一致。这表明您在 CSV 文件的标题行中有语法上无效的标签。请注意上面来自?make.names 的一点,什么是字母取决于您系统的语言环境; CSV 文件可能包含您的文本编辑器将显示的有效字符,但如果 R​​ 未在相同的语言环境中运行,则该字符可能在那里无效,例如?

我会查看 CSV 文件并识别标题行中的任何非 ASCII 字符;标题行中也可能有不可见的字符(或转义序列;\t?)。在读取具有无效名称的文件和在控制台中显示它之间可能会发生很多事情,这可能会掩盖无效字符,所以不要认为没有@它不会显示任何错误987654333@ 表示文件正常。

发布sessionInfo() 的输出也会很有用。

【讨论】:

不错的答案 Gavin +1 我想知道标题名称前面是否有空格,因为make.names(" Foo") 也会创建"X.Foo" 是否可以使用其他字符代替X 这个完美答案的一个非常简单的总结是,如果您不想让 R 更改您的名字,请尝试将其添加到您的 read.table() 中:check.names=FALSE【参考方案2】:

我刚刚遇到这个问题,原因很简单。我有以数字开头的标签,而 R 在它们前面添加了一个 X。我认为 R 与标题中的数字混淆,并应用字母来区分值。

所以,“3_in”变成了“X3_in”等等...... 我通过将标签切换为“in_3”解决了问题,问题得到了解决。

我希望这对某人有所帮助。

【讨论】:

谢谢马特。你是如何系统地删除“x”的。并用“in_”附加所有列?【参考方案3】:

当列名的格式不正确时,R 在导入期间在列名的开头放置一个“X”。例如,当您的列名以数字或某些空格字符开头时,通常会发生这种情况。 check.names = FALSE 因为它不会发生 - 不会有“X”。 但是,如果列名以数字或其他特殊字符开头,则某些功能可能不起作用。例如rbind.fill 函数。

因此,在应用该功能(使用“更正的 colnames”)之后,我使用这个简单的东西来摆脱“X”。

destroyX = function(es) 
  f = es
  for (col in c(1:ncol(f))) #for each column in dataframe
    if (startsWith(colnames(f)[col], "X") == TRUE)   #if starts with 'X' ..
      colnames(f)[col] <- substr(colnames(f)[col], 2, 100) #get rid of it
    
  
  assign(deparse(substitute(es)), f, inherits = TRUE) #assign corrected data to original name

【讨论】:

【参考方案4】:

我遇到了类似的问题,想分享以下代码行来更正列名。当然不是完美的,因为正手的干净编程会更好,但作为快速而肮脏的方法的起点可能会有所帮助。 (我希望将它们添加为对 Ryan 的问题/Gavin 的回答的评论,但我的声誉不够高,所以我不得不发布一个额外的答案 - 抱歉)。

在我的例子中,写入和读取数据的几个步骤产生了一个或多个名为“X”,X.1“,...的列,其中包含 X 列中的内容和 X.1 中的行号,... -columns。在我的情况下,X-column 的内容应该用作行名,而其他 X.1,...-columns 应该被删除。

Correct_Colnames <- function(df) 

 delete.columns <- grep("(^X$)|(^X\\.)(\\d+)($)", colnames(df), perl=T)

  if (length(delete.columns) > 0) 

   row.names(df) <- as.character(df[, grep("^X$", colnames(df))])
   #other data types might apply than character or 
   #introduction of a new separate column might be suitable

   df <- df[,-delete.columns]

   colnames(df) <- gsub("^X", "",  colnames(df))
   #X might be replaced by different characters, instead of being deleted
  

  return(df)

【讨论】:

【参考方案5】:

我通过在write.csv 函数中包含row.names=FALSE 作为参数解决了类似的问题。 write.csv 将行名称作为未命名列包含在 CSV 文件中,read.csv 在读取 CSV 文件时将该列命名为“X”。

【讨论】:

以上是关于为啥在读取数据框时我的列名中出现 X.?的主要内容,如果未能解决你的问题,请参考以下文章

c#从数据库中读取图片出现参数无效

c#从数据库中读取图片出现参数无效

无法从数据流中的 GCS 读取我的配置文本文件(列名)

iOS MagicalRecord 之谜。为啥在 truncateAll 后重新启动时我的数据会重新出现?

R 中的 RODBC 包使用引号创建列名......为啥?

在节点中使用 d3 读取 csv 数据的最佳实践。为啥会出现 TypeError?