【问题标题】:Read columns with readr using regular expressions使用正则表达式使用 readr 读取列
【发布时间】:2019-11-09 05:42:34
【问题描述】:

我需要导入具有不同列号的数据文件。最后,代码应该由其他不太熟悉 R 的同事使用。所以它应该是健壮的并且最好没有警告消息。主要问题是标题总是以一个额外的“,”结尾,它没有出现在下面的数据中。除了一大堆未使用的列之外,所需的列总是以相同的方式标记。 IE。列名中总是有一个特定的字符串,但不一定整个列名都相同。

示例代码是我的文件的一个非常简单的近似值。首先,由于标题末尾的错误逗号,我想摆脱错误消息。类似于skip_col = ncol(headder)。其次,我想只阅读列名中带有"*des*" 的列。

在这个简化的示例中,我处理它的方法看起来很简单,但在我更复杂的代码中却不是很令人满意。

library(tidyverse)

read_csv("date,col1des,col1foo,col2des,col3des,col2foo,col3foo, 
          2015-10-23T22:00:00Z,0.6,-1.5,-1.3,-0.5,1.8,0 
          2015-10-23T22:10:00Z,-0.5,-0.6,1.5,0.1,-0.3,0.3
          2015-10-23T22:20:00Z,0.1,0.2,-1.6,-0.1,-1.4,-0.4
          2015-10-23T22:30:00Z,1.7,-1.2,-0.2,-0.4,0.3,0.3")

if (length(grep("des", names(data))) > 0) {
  des <- data[grep("des", names(data))]
  des <- bind_cols(date = data$date, des)
}

所以在我的完整代码中,我收到以下警告消息:

1. Missing column names filled in: 'X184' [184] 
2. Duplicated column names deduplicated: [long list of unrequired columns with dublicated names]

我希望能在 tidyverse 中找到解决方案。据我发现,不可能直接在read_csv 调用中使用正则表达式来指定列名,对吧?因此,也许唯一的方法是首先阅读标题并从中构建cols() 调用。但这超出了我的 R 知识。

编辑:

我想知道这样的事情是否可能:

headline <- "date,col1des,col1foo,col2des,col3des,col2foo,col3foo,"
head     <- headline %>% strsplit(",") %>% unlist(use.names = FALSE)
head_des <- head[grep("des", head)]
data     <- read_csv("mydata.csv", col_types = cols_only(head_des[1] = "d", head_des[2] = "d"))

我想grep() 列名,然后才能读取整个数据。

【问题讨论】:

  • d &lt;- suppressWarnings(readr::read_csv("text...")); d[, grep("des", names(d))]?
  • 谢谢,在我的情况下,抑制所有警告非常有用。但我想我可以以某种方式避免直接阅读read_csv () 调用中的所有其他列。 grep () 就是我现在正在做的事情。不幸的是,它并不那么优雅,因为我必须搜索多个字符串和多达 200 个未使用的列,其中包含大量数据。
  • grep 你可以使用|,例如grep("str1|str2", names)。不过,这可能会意外匹配您可以使用 regular expressions 解决的不需要的列。

标签: r readr


【解决方案1】:

编辑编号2

回应您的评论; 这适用于您的数据字符串:

library(tidyverse)
yourData <- "date,col1des,col1foo,col2des,col3des,col2foo,col3foo, 
          2015-10-23T22:00:00Z,0.6,-1.5,-1.3,-0.5,1.8,0 
          2015-10-23T22:10:00Z,-0.5,-0.6,1.5,0.1,-0.3,0.3
          2015-10-23T22:20:00Z,0.1,0.2,-1.6,-0.1,-1.4,-0.4
          2015-10-23T22:30:00Z,1.7,-1.2,-0.2,-0.4,0.3,0.3"

data <- suppressWarnings(read_csv(yourData))

header <- names(data)
colList <- ifelse(str_detect(header,'des'),'c','_') %>% as.list
suppressWarnings(read_csv(yourData,col_types = do.call(cols_only, colList)))
#> # A tibble: 4 x 3
#>   col1des col2des col3des
#>   <chr>   <chr>   <chr>  
#> 1 0.6     -1.3    -0.5   
#> 2 -0.5    1.5     0.1    
#> 3 0.1     -1.6    -0.1   
#> 4 1.7     -0.2    -0.4

编辑

this Post 的帮助下尝试满足您编辑的愿望:


library(tidyverse)


header <- suppressWarnings(readLines('file.csv')[1]) %>% 
  str_split(',',simplify = T)
colList <- ifelse(str_detect(header,'des'),'c','_') %>% as.list
suppressWarnings(read_csv(file = 'file.csv',col_types = do.call(cols_only, colList)))
#> # A tibble: 4 x 3
#>   col1des col2des col3des
#>   <chr>   <chr>   <chr>  
#> 1 0.6     -1.3    -0.5   
#> 2 -0.5    1.5     0.1    
#> 3 0.1     -1.6    -0.1   
#> 4 1.7     -0.2    -0.4

这是我能想到的最强大、最tidyverse 的方式:

library(tidyverse)

file <- suppressWarnings(readLines('file.csv')) %>% 
  str_split(',') 
dims <- file %>% map_int(~length(.))
if(any(dims != median(dims))){
  file[[which(dims != median(dims))]] <- file[[which(dims != median(dims))]][1:median(dims)]
}
data <- file %>% map_chr(~paste(.,collapse = ',')) %>% 
  paste(., sep = '\n') %>% read_csv
(data <- data %>% select(which(str_detect(names(data), pattern = 'des'))))
#> # A tibble: 4 x 3
#>   col1des col2des col3des
#>     <dbl>   <dbl>   <dbl>
#> 1     0.6    -1.3    -0.5
#> 2    -0.5     1.5     0.1
#> 3     0.1    -1.6    -0.1
#> 4     1.7    -0.2    -0.4

file.csv 包含您的数据的位置。

【讨论】:

  • 如果我只是运行你的代码,我不得不承认我不完全理解,它会出现错误消息:Error: 'date,col1des,col1foo,col2des,col3des,col2foo,col3foo2015-10-23T22:00:00Z,0.6,-1.5,-1.3,-0.5,1.8,02015-10-23T22:10:00Z,-0.5,-0.6,1.5,0.1,-0.3,0.32015-10-23T22:20:00Z,0.1,0.2,-1.6,-0.1,-1.4,-0.42015-10-23T22:30:00Z,1.7,-1.2,-0.2,-0.4,0.3,0.3' does not exist in current working directory
  • 您必须将数据保存在当前工作目录中的文本文件中,并将其命名为“file.csv”才能正常工作。 readLines 打开一个文件并将其拆分为一个 character-vector,每行输入一个条目。
  • read_csv(yourData,col_types = do.call(cols_only, colList)) 这正是我所需要的!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-25
  • 2020-09-06
  • 1970-01-01
  • 2013-04-08
  • 2013-01-04
相关资源
最近更新 更多