【问题标题】:Reading in Poor CSV File Structure读取糟糕的 CSV 文件结构
【发布时间】:2017-01-09 02:54:02
【问题描述】:

我正在尝试读取一个大型 csv 数据文件(由 , 分隔),但我一直卡在如下行中: 原始文件链接:“http://daniels-pull.universityofdenv.netdna-cdn.com/assets/GeneralOccurrencesAll.csv

| RIN    | UCR_Group | Loc                                         |
|--------|-----------|---------------------------------------------|
|490658  | Property  | 400 BLOCK 17TH ST, 5TH FL                   |
|506928  | Disorder  | 1400 BLOCK W COLORADO AVE, COLORADO SPRINGS |

如您所见,列中也使用了文件的分隔符。有没有办法将列的分隔符指定为要在文件中读取的正则表达式,还是我需要研究使用 read.fwf 来查找每个字段的最大长度,并使用它解析数据? 目前,这是我到目前为止提出的代码:

datafile <- "http://daniels-pull.universityofdenv.netdna-cdn.com/assets/GeneralOccurrencesAll.csv"
new <-readr::read_delim(datafile, sep ='[\\S],[\\S]')  
new <-read.table(datafile, sep ='[\\S],[\\S]' )

我应该使用 read.fwf,还是尝试手动提取问题列?任何帮助将不胜感激。

编辑:

对于奖励积分,我真的很想构建一个函数来检测 csv 文件中的坏列,或者看起来可能会破坏文件结构的数据,例如这种情况。这样,我就不必乱用文本编辑器,并且可以以编程方式在文件中找到这些错误。关于如何构建这样的东西的想法?

【问题讨论】:

  • 是的 readr::read_csv 有效,但有错误。我希望我可以提供一个正则表达式作为 R 中的分隔符,但我想不是。我只是想知道是否有更优雅的方式,例如 read.table 或使用 fread 逐列拉入数据可能更容易。
  • 如果它甚至可以在 pandas 中进行,那将是非常棒的,但我更喜欢 r.根据这个网站,我知道我的数据结构不好:csvlint.io/validation/5872bb3e3738390004000005
  • @petergensler 我认为@darshan-baral 表示来自base R 的原始read.csv
  • 不,我认为 read.csv 不起作用...我收到此错误:read.csv(datafile, header = TRUE, sep = '[\\S],[\\S] ') 扫描错误(文件,what = "",sep = sep,quote = quote,nlines = 1,quiet = TRUE,:无效​​的 'sep' 值:必须是一个字节
  • @petergensler - readLines("filename") 几乎是最小的 :-)

标签: r csv pandas readr


【解决方案1】:

使用panda.read_csv 和正则表达式否定向前看。同样的正则表达式也应该在R 中工作。

import pandas as pd

df = pd.read_csv(filename, sep=r',(?!\s)')

过滤dfLOC 有逗号的行,以验证我们是否已正确解析:

df[df.LOC.str.contains(',')]

【讨论】:

  • 你是如何设计你的正则表达式的?我已经尝试了好几天......你在哪里测试你的正则表达式?
【解决方案2】:

用分号替换每个被非空格包围的逗号,然后使用read.csv2 读入结果。

(将Lines 替换为readLines(u) 命令以从u 读取它。此外,如果文件中有分号,则使用不同的字符并在sep= 参数中指定它read.csv2 或只是@ 987654327@ 并在第二个参数中为gsub。)

read.csv2(text = gsub(",(\\S)", ";\\1", Lines)))

给予:

     RIN UCR_Group                                         Loc
1 490658  Property                   400 BLOCK 17TH ST, 5TH FL
2 506928  Disorder 1400 BLOCK W COLORADO AVE, COLORADO SPRINGS

注意:我们使用这个作为输入Lines

Lines <- c("RIN,UCR_Group,Loc", 
  "490658,Property,400 BLOCK 17TH ST, 5TH FL", 
  "506928,Disorder,1400 BLOCK W COLORADO AVE, COLORADO SPRINGS")

更新:在实际文件中,有效的逗号分隔符之前似乎可以出现一个空格,并且有一个字符字段,因此我们相应地修改了模式。以下是文件前 3 行的结果:

u <- "http://daniels-pull.universityofdenv.netdna-cdn.com/assets/GeneralOccurrencesAll.csv"
Lines <- readLines(u, 3)

read.csv2(text = gsub(",(\\S)", ";\\1", Lines))

给予:

     RIN               UCR_Group                            UCR_Cat
1 416667 Crimes Against Property Criminal Mischief/Damaged Property
2 416673  Crimes Against Persons              Forcible Sex Offenses
              EXP_TRANSLATION         OCC_DATE OCC_TIME                     LOC
1 CRIMINAL MISCHIEF - MTR VEH 1/1/2010 0:00:00      145  200 BLOCK S ZENOBIA ST
2             SEX ASLT - RAPE 1/1/2010 0:00:00      300 1500 BLOCK S DECATUR ST
  TRANSLATION       PIN               DOB SEX          X          Y     LON
1 VICTIM      235602181  5/6/1979 0:00:00   M 3126041.08 1684996.73 -105.05
2 ARRESTEE    219220590 3/19/1988 0:00:00   M 3134340.56 1676360.06 -105.02
    LAT
1 39.71
2 39.68

【讨论】:

  • 我认为这不适用于原始数据文件,但它确实适用于您所说的提供的向量。
  • 似乎问题中的描述并不完全准确,因为存在以空格开头的有效逗号分隔符。还有一个字符字段,而简短示例中没有。我已经相应地修改了代码,所以它应该可以在文件上工作。
  • 对此表示歉意。我应该更清楚。基于您的答案,您将如何使用您的逻辑来搜索文件中可能无法正确解析它的任何分隔符?我敢肯定很多其他人都遇到过类似的问题
  • 是否有任何资源可以学习使用文本连接将文件读入 R?这似乎是一个非常方便的功能,但我怀疑是否有人熟悉如何正确利用它
  • 基于您的方法,这就是我清理文件的方式:system.time(genocc
【解决方案3】:

你知道哪个字段有非转义逗号:

library(stringi)
library(purrr)

txt <- readr::read_lines("http://daniels-pull.universityofdenv.netdna-cdn.com/assets/GeneralOccurrencesAll.csv")
commas <- stri_locate_all_fixed(txt, ",")

map2_chr(txt[1:100], commas[1:100], function(x, y) {
  len <- nrow(y)
  bits <- c(1:6, (len-6):len)
  for (i in bits) { stri_sub(x, y[i,1], y[i,2]) <- ";" }
  x
}) -> rd

read.table(text=rd, header=TRUE, sep=";", stringsAsFactors=FALSE) %>%
  dplyr::glimpse()
## Observations: 99
## Variables: 14
## $ RIN             <int> 416667, 416673, 416674, 416680, 416684, 416686...
## $ UCR_Group       <chr> "Crimes Against Property", "Crimes Against Per...
## $ UCR_Cat         <chr> "Criminal Mischief/Damaged Property", "Forcibl...
## $ EXP_TRANSLATION <chr> "CRIMINAL MISCHIEF - MTR VEH", "SEX ASLT - RAP...
## $ OCC_DATE        <chr> "1/1/2010 0:00:00", "1/1/2010 0:00:00", "1/1/2...
## $ OCC_TIME        <int> 145, 300, 500, 730, 200, 440, 100, 851, 140, 2...
## $ LOC.TRANSLATION <chr> "200 BLOCK S ZENOBIA ST,VICTIM     ", "1500 BL...
## $ PIN             <int> 235602181, 219220590, 119013720, 174326399, 32...
## $ DOB             <chr> "5/6/1979 0:00:00", "3/19/1988 0:00:00", "5/25...
## $ SEX             <chr> "M", "M", "M", "M", "F", "F", "F", "F", "F", "...
## $ X               <dbl> 3126041, 3134341, 3134360, 3127695, 3193317, 3...
## $ Y               <dbl> 1684997, 1676360, 1700160, 1682545, 1708673, 1...
## $ LON             <dbl> -105.05, -105.02, -105.02, -105.04, -104.81, -...
## $ LAT             <dbl> 39.71, 39.68, 39.75, 39.70, 39.77, 39.78, 39.7...

【讨论】:

  • 哇,真是太棒了!你将如何编写一个函数来检测 R 中哪些字段是坏的?这是否可能,而不是在文本编辑器中手动搜索?
  • 是的,这是可能的。找到常见的“逗号”模式,然后将字段与错误的模式隔离开来。
  • 好的,你想建议如何构建一个可以做到这一点的函数?
【解决方案4】:

这是一个工作示例,显示您可以使用正则表达式来解析此文件,这取决于地址中的逗号有空格这一事实。如果这条规则并不总是成立,这当然会变得更加复杂:

txt <- "RIN,UCR_Group,Loc
123456,Property,1 STREET
490658,Property,400 BLOCK 17TH ST, 5TH FL
506928,Disorder,1400 BLOCK W COLORADO AVE, COLORADO SPRINGS"

dat <- readLines(textConnection(txt))
# in a real example:
# dat <- readLines("filename.csv")

spl <- strsplit(dat, "(?<=\\S),(?=\\S)", perl=TRUE)
setNames(data.frame(do.call(rbind, spl[-1])), spl[[1]])

#     RIN UCR_Group                                         Loc
#1 123456  Property                                    1 STREET
#2 490658  Property                   400 BLOCK 17TH ST, 5TH FL
#3 506928  Disorder 1400 BLOCK W COLORADO AVE, COLORADO SPRINGS

【讨论】:

    猜你喜欢
    • 2020-05-08
    • 2021-10-02
    • 2014-06-30
    • 2018-07-06
    • 2014-09-07
    • 2017-01-23
    • 1970-01-01
    • 1970-01-01
    • 2013-11-14
    相关资源
    最近更新 更多