How long was the file that you tested?  Here is a test with a file
that is 110400 lines long with 4416 replicated headers that will have
to be removed.  Using 'text=' or textConnection is very slow for these
operations.

Writing to a temporary file can be faster for especially large files.
Notice that this is the fastest method for this file.

Here are three approaches and their times:

############################

> system.time({
+     # approach #1 - read in file and then delete rows with NAs
+     x <- read.table('/temp/text.txt', as.is = TRUE, header = TRUE)
+     # convert to numeric
+     x[] <- lapply(x, as.numeric)
+     x <- x[!is.na(x[,1]), ]
+ })
   user  system elapsed
   0.70    0.00    0.72
Warning messages:
1: In lapply(x, as.numeric) : NAs introduced by coercion
2: In lapply(x, as.numeric) : NAs introduced by coercion
3: In lapply(x, as.numeric) : NAs introduced by coercion
4: In lapply(x, as.numeric) : NAs introduced by coercion
5: In lapply(x, as.numeric) : NAs introduced by coercion
> str(x)
'data.frame':   105984 obs. of  5 variables:
 $ a: num  1 1 1 1 1 1 1 1 1 1 ...
 $ b: num  2 2 2 2 2 2 2 2 2 2 ...
 $ c: num  3 3 3 3 3 3 3 3 3 3 ...
 $ d: num  4 4 4 4 4 4 4 4 4 4 ...
 $ e: num  5 5 5 5 5 5 5 5 5 5 ...
> colSums(x)
     a      b      c      d      e
105984 211968 317952 423936 529920
>
> system.time({
+     # approach #2 -- read the lines, delete header, rewrite to temp file
+     # and then read in with read.table
+     x <- readLines('/temp/text.txt')
+     firstLine <- x[1L]  # save header since deleted by 'grepl'
+     x <- c(firstLine, x[grepl("^[0-9]", x)])  # accept only lines
that start with numeric
+     temp <- tempfile()
+     writeLines(x, temp)
+     x <- read.table(temp, as.is = TRUE, header = TRUE)
+ })
   user  system elapsed
   0.55    0.02    0.56
> str(x)
'data.frame':   105984 obs. of  5 variables:
 $ a: int  1 1 1 1 1 1 1 1 1 1 ...
 $ b: int  2 2 2 2 2 2 2 2 2 2 ...
 $ c: int  3 3 3 3 3 3 3 3 3 3 ...
 $ d: int  4 4 4 4 4 4 4 4 4 4 ...
 $ e: int  5 5 5 5 5 5 5 5 5 5 ...
> colSums(x)
     a      b      c      d      e
105984 211968 317952 423936 529920

> system.time({
+     # approach #3 -- read the lines, delete header, then use 'text'
on read.table
+     x <- readLines('/temp/text.txt')
+     firstLine <- x[1L]
+     x <- c(firstLine, x[grepl("^[0-9]", x)])
+     x <- read.table(text = x, as.is = TRUE, header = TRUE)
+ })
   user  system elapsed
  29.01    0.01   29.62
> str(x)
'data.frame':   105984 obs. of  5 variables:
 $ a: int  1 1 1 1 1 1 1 1 1 1 ...
 $ b: int  2 2 2 2 2 2 2 2 2 2 ...
 $ c: int  3 3 3 3 3 3 3 3 3 3 ...
 $ d: int  4 4 4 4 4 4 4 4 4 4 ...
 $ e: int  5 5 5 5 5 5 5 5 5 5 ...
> colSums(x)
     a      b      c      d      e
105984 211968 317952 423936 529920


On Wed, Nov 28, 2012 at 7:01 PM, Nordlund, Dan (DSHS/RDA)
<[email protected]> wrote:
>> -----Original Message-----
>> From: [email protected] [mailto:r-help-bounces@r-
>> project.org] On Behalf Of Fisher Dennis
>> Sent: Wednesday, November 28, 2012 11:42 AM
>> To: [email protected]
>> Cc: [email protected]
>> Subject: Re: [R] Speeding reading of large file
>>
>> An interesting approach -- I lose the column names (which I need) but I
>> could get them with something cute such as:
>>       1.  read the first few lines only with readLines(FILENAME, n=10)
>>       2.  use your approach to read.table -- this will grab the column
>> names
>>       3.  replace the headers in the full version with the correct
>> column names
>>
>> Dennis Fisher MD
>> P < (The "P Less Than" Company)
>> Phone: 1-866-PLessThan (1-866-753-7784)
>> Fax: 1-866-PLessThan (1-866-753-7784)
>> www.PLessThan.com
>>
>> On Nov 28, 2012, at 11:32 AM, David L Carlson wrote:
>>
>> > Using your first approach, this should be faster
>> >
>> > raw <- readLines(con=filename)
>> > dta <- read.table(text=raw[!grepl("[A:DF:Z]" ,raw)], header=FALSE)
>> >
>> > ----------------------------------------------
>> > David L Carlson
>> > Associate Professor of Anthropology
>> > Texas A&M University
>> > College Station, TX 77843-4352
>> >
>> >> -----Original Message-----
>> >> From: [email protected] [mailto:r-help-bounces@r-
>> >> project.org] On Behalf Of Fisher Dennis
>> >> Sent: Wednesday, November 28, 2012 11:43 AM
>> >> To: [email protected]
>> >> Subject: [R] Speeding reading of large file
>> >>
>> >> R 2.15.1
>> >> OS X and Windows
>> >>
>> >> Colleagues,
>> >>
>> >> I have a file that looks that this:
>> >> TABLE NO.  1
>> >> PTID        TIME        AMT         FORM        PERIOD      IPRED
>> >> CWRES       EVID        CP          PRED        RES         WRES
>> >>  2.0010E+03  3.9375E-01  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 0.0000E+00  0.0000E+00  1.0000E+00  0.0000E+00  0.0000E+00
>> 0.0000E+00
>> >> 0.0000E+00
>> >>  2.0010E+03  8.9583E-01  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 3.3389E+00  0.0000E+00  1.0000E+00  0.0000E+00  3.5321E+00
>> 0.0000E+00
>> >> 0.0000E+00
>> >>  2.0010E+03  1.4583E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 5.8164E+00  0.0000E+00  1.0000E+00  0.0000E+00  5.9300E+00
>> 0.0000E+00
>> >> 0.0000E+00
>> >>  2.0010E+03  1.9167E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 8.3633E+00  0.0000E+00  1.0000E+00  0.0000E+00  8.7011E+00
>> 0.0000E+00
>> >> 0.0000E+00
>> >>  2.0010E+03  2.4167E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.0092E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.0324E+01
>> 0.0000E+00
>> >> 0.0000E+00
>> >>  2.0010E+03  2.9375E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.1490E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.1688E+01
>> 0.0000E+00
>> >> 0.0000E+00
>> >>  2.0010E+03  3.4167E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.2940E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.3236E+01
>> 0.0000E+00
>> >> 0.0000E+00
>> >>  2.0010E+03  4.4583E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.1267E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.1324E+01
>> 0.0000E+00
>> >> 0.0000E+00
>> >>
>> >> The file is reasonably large (> 10^6 lines) and the two line header
>> is
>> >> repeated periodically in the file.
>> >> I need to read this file in as a data frame.  Note that the number
>> of
>> >> columns, the column headers, and the number of replicates of the
>> >> headers are not known in advance.
>> >>
>> >> I have tried two approaches to this:
>> >>    First Approach:
>> >>            1.  readLines(FILENAME) to read in the file
>> >>            2.  use grep to find the repeat headers; strip out the
>> >> repeat headers
>> >>            3.  write() the object to tempfile, read in that temporary
>> >> file using read.table(tempfile, header=TRUE, skip=1) [an alternative
>> is
>> >> to use textConnection but that does not appear to speed things]
>> >>
>> >>    Second Approach:
>> >>            1.  TEMP        <- read.table(FILENAME, header=TRUE, skip=1,
>> >> fill=TRUE, as.is=TRUE)
>> >>            2.  get rid of the errant entries with:
>> >>                    TEMP[!is.na(as.numeric(TEMP[,1])),]
>> >>            3.  reading of the character entries forced all columns to
>> >> character mode.  Therefore, I convert each column to numeric:
>> >>                    for (COL in 1:ncol(TEMP)) TEMP[,COL] <-
>> >> as.numeric(TEMP[,COL])
>> >> The second approach is ~ 20% faster than the first.  With the second
>> >> approach, the conversion to numeric occupies 50% of the elapsed
>> time.
>> >>
>> >> Is there some approach that would be much faster?  For example,
>> would a
>> >> vectorized approach to conversion to numeric improve throughput?
>> Or,
>> >> is there some means to ensure that all data are read as numeric (I
>> >> tried to use colClasses but that triggered an error when the text
>> >> string was encountered).
>> >>
>> >> ############################
>> >> A dput version of the data is:
>> >> c("TABLE NO.  1", " PTID        TIME        AMT         FORM
>> >> PERIOD      IPRED       CWRES       EVID        CP          PRED
>> >> RES         WRES",
>> >> "  2.0010E+03  3.9375E-01  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 0.0000E+00  0.0000E+00  1.0000E+00  0.0000E+00  0.0000E+00
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  8.9583E-01  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 3.3389E+00  0.0000E+00  1.0000E+00  0.0000E+00  3.5321E+00
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  1.4583E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 5.8164E+00  0.0000E+00  1.0000E+00  0.0000E+00  5.9300E+00
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  1.9167E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 8.3633E+00  0.0000E+00  1.0000E+00  0.0000E+00  8.7011E+00
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  2.4167E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.0092E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.0324E+01
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  2.9375E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.1490E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.1688E+01
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  3.4167E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.2940E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.3236E+01
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  4.4583E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.1267E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.1324E+01
>> 0.0000E+00
>> >> 0.0000E+00"
>> >> )
>> >>
>> >> This can be assembled into a large dataset and written to a file
>> named
>> >> FILENAME with the following code:
>> >> cat(c("TABLE NO.  1", " PTID        TIME        AMT         FORM
>> >> PERIOD      IPRED       CWRES       EVID        CP          PRED
>> >> RES         WRES",
>> >> "  2.0010E+03  3.9375E-01  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 0.0000E+00  0.0000E+00  1.0000E+00  0.0000E+00  0.0000E+00
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  8.9583E-01  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 3.3389E+00  0.0000E+00  1.0000E+00  0.0000E+00  3.5321E+00
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  1.4583E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 5.8164E+00  0.0000E+00  1.0000E+00  0.0000E+00  5.9300E+00
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  1.9167E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 8.3633E+00  0.0000E+00  1.0000E+00  0.0000E+00  8.7011E+00
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  2.4167E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.0092E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.0324E+01
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  2.9375E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.1490E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.1688E+01
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  3.4167E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.2940E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.3236E+01
>> 0.0000E+00
>> >> 0.0000E+00",
>> >> "  2.0010E+03  4.4583E+00  5.0000E+03  2.0000E+00  0.0000E+00
>> >> 1.1267E+01  0.0000E+00  1.0000E+00  0.0000E+00  1.1324E+01
>> 0.0000E+00
>> >> 0.0000E+00"
>> >> )[rep(1:10, 1000)], file="FILENAME", sep="\n")
>> >>
>> >>
>> >> Dennis
>> >>
>> >>
>
> Dennis,
>
> I used your code to create the test file, and then used two different method 
> to read the file
>
> # method 1
> system.time({
> fisher <- read.table('c:/tmp/fisher.txt', header=TRUE,skip=1,fill=TRUE, 
> as.is=TRUE)
> fisher <- data.frame(apply(fisher,2,as.numeric))
> fisher <- fisher[!is.na(fisher$PTID),]
> })
>    user  system elapsed
>    0.14    0.00    0.14
> There were 12 warnings (use warnings() to see them)
>
> # method 2
> system.time({
> raw <- readLines(con='c:/tmp/fisher.txt')
> fisher2 <- read.table(text=raw[!grepl("[A:DF:Z]" ,raw)], header=FALSE, 
> fill=TRUE)
> names <- read.table('c:/tmp/fisher.txt',header=TRUE,skip=1,nrows=1)
> colnames(fisher2) <- colnames(names)
> })
>    user  system elapsed
>    1.31    0.00    1.31
>
> Method 1 was substantially faster than method 2.  One thing I don't like 
> about method 1 is the warnings (about NA's being created by as.numeric).  
> However they are essentially harmless.
>
>
> Hope this is helpful,
>
> Dan
>
> Daniel J. Nordlund
> Washington State Department of Social and Health Services
> Planning, Performance, and Accountability
> Research and Data Analysis Division
> Olympia, WA 98504-5204
>
> ______________________________________________
> [email protected] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.



-- 
Jim Holtman
Data Munger Guru

What is the problem that you are trying to solve?
Tell me what you want to do, not how you want to do it.

______________________________________________
[email protected] mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to