【问题标题】:Creating A Dataframe From A Text Dataset从文本数据集创建数据框
【发布时间】:2014-04-15 16:34:59
【问题描述】:

我有一个包含数十万个字段的数据集。下面是一个简化的数据集

dataSet <- c("Plnt SLoc Material           Description              L.T MRP Stat Auto MatSG PC PN    Freq  Qty    CFreq     CQty Cur.RPt New.RPt CurRepl NewRepl Updt    Cost   ServStock  Unit  OpenMatResb DFStorLocLevel", 
"0231 0002 GB.C152260-00001   ASSY PISTON & SEAL/O-RING 44  PD       X    A    A  A     18     136                     30      29      50      43         24.88      51.000  EA", 
"0231 0002 WH.112734          MOTOR REDUCER, THREE-PHAS 41  PD       X    B    B  A     16      17                      3       3       5       4        483.87       1.000  EA      X", 
"0231 0002 WH.920569          SPINDLE MOTOR MINI O      22  PD       X    A    A  A     69      85                     15       9      25      13        680.91      21.000  EA", 
"0231 0002 GB.C150583-00001   VALVE-AIR MDI             64  PD       X    A    A  A     16     113                     50      35      80      52         19.96     116.000  EA", 
"0231 0002 FG.124-0140        BEARING                   32  PD       X    A    A  A     36     205                     35      32      50      48         21.16      55.000  EA", 
"0231 0002 WP.254997          BEARING,BALL .9843 X 2.04 52  PD       X    A    A  A     18     155                     50      39     100      58          2.69     181.000  EA"
)

我想用这个数据集创建一个数据框以供进一步计算。我遵循的方法如下:

我将数据集按空格拆分,然后重新组合。

dataSetSplit <- strsplit(dataSet, "\\s+")

标题(即第一行)正确拆分并生成 25 个字符。这可以通过 str() 函数看到。

str(dataSetSplit)

然后我打算使用以下脚本将所有行组合在一起

combinedData  <-  data.frame(do.call(rbind, dataSetSplit))

请注意,上面的脚本“combinedData”错误,因为拆分没有产生相等数量的字段。

要使这种方法起作用,所有字段必须正确拆分为 25 个字段。

如果您认为这是一种合理的方法请告诉我如何将文件分成 25 个字段

值得一提的是,我不喜欢用函数 strsplit() 分割数据集的方法。如果与大型数据集一起使用,这是一个非常耗时的步骤。 您能否推荐一种替代方法来根据提供的数据创建数据框?

【问题讨论】:

  • 这看起来像是固定宽度的数据。请查看read.fwf
  • 你最初是如何加载数据的?
  • 我的答案是否停止工作?如果是这样,注释有助于解释为什么“已接受”状态被删除,从而表明此问题仍未解决。已解决的问题使 SO 成为其他试图在未来解决类似问题的人的宝贵资源。

标签: regex r dataframe


【解决方案1】:

从外观上看,您有一个实际上很有帮助的标题行。您可以轻松地使用gregexpr 来计算您的“宽度”以用于read.fwf

方法如下:

## Use gregexpr to find the position of consecutive runs of spaces
## This will tell you the starting position of each column
Widths <- gregexpr("\\s+", dataSet[1])[[1]]

## `read.fwf` doesn't need the starting position, but the width of
##   each column. We can use `diff` to calculate this. 
Widths <- c(Widths[1], diff(Widths))

## Since there are no spaces after the last column, we need to calculate
##   a reasonable width for that column too. We can do this with `nchar`
##   to find the widest row in the data. From this, subtract the `sum`
##   of all the previous values.
Widths <- c(Widths, max(nchar(dataSet)) - sum(Widths))

让我们也提取列名。我们可以在read.fwf 中执行此操作,但这需要我们将第一行中的空格替换为“sep”字符。

Names <- scan(what = "", text = dataSet[1])

现在,阅读除第一行以外的所有内容。我想你会使用实际文件而不是textConnection

read.fwf(textConnection(dataSet), widths=Widths, strip.white = TRUE, 
         skip = 1, col.names = Names)
#   Plnt SLoc         Material               Description L.T MRP Stat Auto MatSG PC PN Freq Qty
# 1  231    2 GB.C152260-00001 ASSY PISTON & SEAL/O-RING  44  PD   NA    X     A  A  A   18 136
# 2  231    2        WH.112734 MOTOR REDUCER, THREE-PHAS  41  PD   NA    X     B  B  A   16  17
# 3  231    2        WH.920569      SPINDLE MOTOR MINI O  22  PD   NA    X     A  A  A   69  85
# 4  231    2 GB.C150583-00001             VALVE-AIR MDI  64  PD   NA    X     A  A  A   16 113
# 5  231    2      FG.124-0140                   BEARING  32  PD   NA    X     A  A  A   36 205
# 6  231    2        WP.254997 BEARING,BALL .9843 X 2.04  52  PD   NA    X     A  A  A   18 155
#   CFreq CQty Cur.RPt New.RPt CurRepl NewRepl Updt   Cost ServStock Unit OpenMatResb
# 1    NA   NA      30      29      50      43   NA  24.88        51   EA        <NA>
# 2    NA   NA       3       3       5       4   NA 483.87         1   EA           X
# 3    NA   NA      15       9      25      13   NA 680.91        21   EA        <NA>
# 4    NA   NA      50      35      80      52   NA  19.96       116   EA        <NA>
# 5    NA   NA      35      32      50      48   NA  21.16        55   EA        <NA>
# 6    NA   NA      50      39     100      58   NA   2.69       181   EA        <NA>
#   DFStorLocLevel
# 1             NA
# 2             NA
# 3             NA
# 4             NA
# 5             NA
# 6             NA

【讨论】:

  • Ananda Mahto,您能解释一下三个宽度脚本吗?谢谢
  • 嗨 Ananda,diff 没有正确计算每列的宽度。例如,第 3 列“材料”计算的宽度是 9,但实际上它应该是 19 宽度
  • 我认为对象“宽度”+尾随空格数应该等于列宽。关键是提取每列的尾随空格数。
  • @RagyIsaac,我在进行计算的工作区中一定有一些剩余信息。以后有机会我会再看的。
【解决方案2】:

非常感谢 Ananda Mahto,他为这个答案提供了很多内容。

widthMinusFirst <- diff(gregexpr('(\\s[A-Z])+', dataSet[1])[[1]])
widthFirst <- gregexpr('\\s+', dataSet[1])[[1]][1]
Width <- c(widthFirst, widthMinusFirst)

Widths <- c(Width, max(nchar(dataSet)) - sum(Width))
columnNames <- scan(what = "", text = dataSet[1])

read.fwf(textConnection(dataSet[-1]), widths = Widths, strip.white = FALSE,
         skip = 0, col.names = columnNames)

【讨论】:

    猜你喜欢
    • 2019-09-25
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    • 2018-04-12
    • 1970-01-01
    • 2021-12-28
    • 2019-08-09
    • 2020-02-26
    相关资源
    最近更新 更多