从文本数据集创建数据框

时间:2014-04-15 16:35:00

标签: regex r dataframe

我有一个拥有数十万个字段的数据集。以下是简化数据集

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"
)

我想从这个数据集中创建一个数据帧,以便进一步计算。我遵循的方法如下:

我按空格分割dataSet,然后重新组合它。

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

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

str(dataSetSplit)

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

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

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

对于这种工作方法,所有字段必须正确分割为25个字段。

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

值得一提的是,我不喜欢使用函数strsplit()拆分数据集的方法。如果与大型数据集一起使用,这是一个非常耗时的步骤。 您能否建议另一种方法从提供的数据中创建数据框?

2 个答案:

答案 0 :(得分:3)

从它的外观来看,你有一个实际上有用的标题行。您可以轻松使用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

答案 1 :(得分:1)

非常感谢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)