【问题标题】:Tidy dataframes with special characters带有特殊字符的整洁数据框
【发布时间】:2019-12-25 15:49:10
【问题描述】:

我的csv格式数据集(here可用)如下:

我尝试使用以下文档将数据导入 R:

library(tidyverse)
data <- read_csv("<Path to file>\\Sample.csv")

当我尝试使用data$ 提取列时,出现错误:

Error in gsub(reStrip, "", completions, perl = TRUE) : 
  input string 4 is invalid UTF-8

我的数据的 D 列包含数字和特殊字符 * 以及 Pilcrow 符号。此列的最后一行中的数字是 66.1,但后面是 #。同样,第一列包含 * 和 Pilcrow 符号。

我想清理数据,以便对于列 D 和 I,将带有 * 和 Pilcrow 符号的行替换为 NA。另外,“66.1#”转换为“66.1”。

我想要的表格如下:

我想知道如何将 csv 文件导入 R 并将其清理为 R 中所需的格式。最好使用 tidyverse。

【问题讨论】:

  • 我的猜测是这与任何 tidyverse 包无关,而是您使用非标准(可以说是无效的)列名的事实。首先修复这些:删除空格和特殊字符。许多 SO 帖子已经涵盖了这一点,包括 this one。最好在问题中创建一个reproducible example,而不是我们必须下载外部数据
  • 数据是从外部数据库下载的,我故意保留列名。我有很多数据集。如果我可以直接在 R 中使用它们而不必为每个数据集重命名列,那会更有效率。正如我所提到的,我更喜欢 tidyverse 的解决方案,但任何其他解决方案都可以。有了提供的数据,任何人都可以复制我的错误。虽然数据存放在别处,但错误无疑是可重现的。另外,提供的数据集是复制的最小数据集,符合可重现示例的精神。谢谢
  • 链接 https://raw.githubusercontent.com/Patricklv/Dataframe-with-special-characters/master/Sample.csv 上的 CSV 似乎没有 Pilcrow 符号——我在那里看到问号。你觉得它不一样吗?
  • 值中的 pilcrow 对readr::read_csv(path, col_names = F) 来说不是问题。您甚至可以毫无问题地将列名作为文本读取。但到目前为止,我尝试过的任何命名版本都不会让这些名称设置在结果数据框上(setNamespurrr::set_namesmagrittr::set_colnames)。
  • 我关于它不是 tidyverse 特定的评论是我删除 tidyverse 标签的原因,因为这些问题与给出的何时使用该标签的指导不符。此外,并不是要更改文件中的列名,因为无论如何这都是错误的形式。你说当你尝试data$ 时会出现问题,所以我的意思是在做类似的事情之前修复列名

标签: r dplyr readr


【解决方案1】:

这是一个简单的解决方案。

将文件作为 .txt 文件读入:

编辑 1: 由于数据在某些单元格中包含主题标签 #,因此您需要包含参数 comment.char="" 以便 R 将显示其后的数据(但仍会将其视为评论的开头):

df <- read.table("[Your path]/Sample.txt", 
                   header = T, fill = T, quote="", sep="\t", comment.char="")

与其他人一样,我发现您的列标题非常不切实际,因此冒昧地将它们更改为字母表的前十一个字母(仅出于视觉原因;您将有理由保留您的标题):

colnames(df) <- LETTERS[1:11]
df
                                    A     B    C       D     E     F           G       H     I      J    K
1       Adams County, Nebraska(6,10)  31001 ***    62.1  51.4  74.6          25  stable  -5.2  -32.3  32.8
2   Adams County, North Dakota(6,10)  38001 ***       *      *    *  3 or fewer       *     *      *     *
3 Aiken County, South Carolina(6,10)  45003 ***    55.9  51.5  60.6         124  stable  -2.3   -8.8   4.6
4        Aitkin County, Minnesota(6)  27001  ***      ¶     ¶     ¶           ¶       ¶     ¶      ¶     ¶
5   Albemarle County, Virginia(6,10)  51003 ***    49.4  44.1  55.3          64  stable  -2.9  -18.1  15.2
6      Alcona County, Michigan(6,10)  26001 ***  66.1 #  51.2  86.7          17  stable  -3.6  -26.5  26.3

可以通过多种方式完成所需的转换;一种简单的方法是(分别转换两列):

df[,4] <- gsub("\\*|¶", NA, df[,4])
df[,9] <- gsub("\\*|¶", NA, df[,9])

这是一种稍微复杂但更经济的方法(一次转换两列):

df[,c(4,9)] <- lapply(df[,c(4,9)], function(x) gsub("\\*|¶", NA, x))

编辑 2: 如果您想摆脱数据中的主题标签,这将对列 D 执行此操作:

df[,4] <- gsub(" #", "", df[,4])

如果您想在某个列范围内去掉 #,请在该范围内设置 df 的子集并使用 lapply

df[,c([range])] <- lapply(df[,c([range])], function(x) gsub(" #", "", x))

输出是这样的:

df
                                    A     B    C     D     E     F           G       H     I      J    K
1       Adams County, Nebraska(6,10)  31001 ***  62.1  51.4  74.6          25  stable  -5.2  -32.3  32.8
2   Adams County, North Dakota(6,10)  38001 ***   <NA>     *    *  3 or fewer       *   <NA>     *     *
3 Aiken County, South Carolina(6,10)  45003 ***  55.9  51.5  60.6         124  stable  -2.3   -8.8   4.6
4        Aitkin County, Minnesota(6)  27001  ***  <NA>    ¶     ¶           ¶       ¶   <NA>     ¶     ¶
5   Albemarle County, Virginia(6,10)  51003 ***  49.4  44.1  55.3          64  stable  -2.9  -18.1  15.2
6      Alcona County, Michigan(6,10)  26001 ***  66.1  51.2  86.7          17  stable  -3.6  -26.5  26.3

【讨论】:

  • 谢谢你,克里斯。我可以用 R 中的代码重命名列。您的解决方案解决了将 * 和 pilcrow 符号转换为 NA 的问题。但是从 E 列开始的最后一行中的所有值都丢失了。还有什么想法吗?这很重要,因为从数据库下载的数据集中的某些行在 D 列中的数字后面有“#”(# 符号前有一个空格)。
  • E列开始的数据缺失,因为E列的数据串以#结尾!该字符被 R 理解为 comment 的开始,它既不被视为数据也不被视为代码。如果删除.txt文件中的字符,则读入完成。
  • 如果数据中有很多带有#的单元格,有一个更好的解决方案:查看我的编辑
猜你喜欢
  • 2014-03-03
  • 2021-11-02
  • 2023-03-08
  • 1970-01-01
  • 2013-11-24
  • 2015-10-20
  • 2015-07-08
  • 1970-01-01
  • 2023-03-14
相关资源
最近更新 更多