2011-10-25 29 views
8

Tôi có thể sử dụng read.csv hoặc read.csv2 để đọc dữ liệu vào R. Nhưng vấn đề tôi gặp phải là dấu phân cách của tôi là chuỗi nhiều byte thay vì một ký tự đơn. Làm thế nào tôi có thể đối phó với điều này?Làm thế nào để đọc một tập tin văn bản vào GNU R với một dấu phân cách nhiều byte?

+1

chuỗi nhiều byte của bạn là gì? – jthetzel

+0

Tôi tin rằng nếu bạn nhìn vào read.table tổng quát hơn() và đối số sep, bạn có thể sử dụng một chuỗi nhiều byte. – mweylandt

+0

@mweylandt Tôi nghĩ 'read.table()' s 'sep' chỉ chấp nhận các byte đơn (giống với' scan() '). – jthetzel

Trả lời

9

Cung cấp dữ liệu mẫu sẽ giúp ích. Tuy nhiên, bạn có thể thích ứng với những điều sau đây theo nhu cầu của bạn.

Tôi tạo ra một tập tin ví dụ dữ liệu, mà là một chỉ là một tập tin văn bản có chứa những điều sau đây:

1sep2sep3 
1sep2sep3 
1sep2sep3 
1sep2sep3 
1sep2sep3 
1sep2sep3 
1sep2sep3 

tôi lưu nó như là 'test.csv'. Ký tự tách là chuỗi 'sep'. Tôi nghĩ rằng read.csv() sử dụng scan(), chỉ chấp nhận một ký tự duy nhất cho sep. Để có được xung quanh nó, hãy xem xét những điều sau đây:

dat <- readLines('test.csv') 
dat <- gsub("sep", " ", dat) 
dat <- textConnection(dat) 
dat <- read.table(dat) 

readLines() chỉ đọc các dòng trong gsub thay thế chuỗi tách đa ký tự cho một đơn ' ', hoặc bất cứ điều gì là thuận tiện cho dữ liệu của bạn.. Sau đó, textConnection()read.data() đọc mọi thứ trở lại một cách thuận tiện. Đối với các tập dữ liệu nhỏ hơn, điều này sẽ ổn. Nếu bạn có dữ liệu rất lớn, hãy xem xét tiền xử lý với một cái gì đó như AWK để thay thế chuỗi tách nhiều ký tự. Ở trên là từ http://tolstoy.newcastle.edu.au/R/e4/help/08/04/9296.html.

Cập nhật Về nhận xét của bạn, nếu bạn có khoảng trống trong dữ liệu của bạn, sử dụng thiết bị tách thay thế khác nhau. Xem xét thay đổi test.csv tới:

1sep2 2sep3 
1sep2 2sep3 
1sep2 2sep3 
1sep2 2sep3 
1sep2 2sep3 
1sep2 2sep3 
1sep2 2sep3 

Sau đó, với các chức năng sau:

readMulti <- function(x, sep, replace, as.is = T) 
{ 
    dat <- readLines(x) 
    dat <- gsub(sep, replace, dat) 
    dat <- textConnection(dat) 
    dat <- read.table(dat, sep = replace, as.is = as.is) 

    return(dat) 
} 

Hãy thử:

readMulti('test.csv', sep = "sep", replace = "\t", as.is = T) 

Ở đây, bạn thay thế các dấu phân cách gốc với các tab (\t). as.is được chuyển đến read.table() để ngăn các chuỗi bị đọc là các yếu tố, nhưng đó là cuộc gọi của bạn. Nếu bạn có khoảng trắng phức tạp hơn trong dữ liệu của bạn, bạn có thể tìm thấy những lập luận quote trong read.table() hữu ích, hoặc quá trình trước với AWK, perl, vv

Something tương tự với crippledlambda của strsplit() rất có thể là tương đương cho dữ liệu có quy mô vừa. Nếu hiệu suất trở thành một vấn đề, hãy thử cả hai và xem cái nào phù hợp với bạn.

+0

read.table sẽ nhận được thông báo lỗi tương tự.Đề nghị của jthetzel nghe có vẻ tốt. Thực ra tôi đã sử dụng awk để xử lý dữ liệu thô trước khi tôi đọc nó trong R. Nhưng câu hỏi ở đây là cách chúng ta có thể xử lý ký tự trong ký tự tách mới sau gsub (Nói, chúng ta CÓ ' 'trong giá trị trong mã mẫu của bạn). – RobinMin

+0

@RobinMin Thử một bộ tách thay thế khác nhau cho mỗi lần cập nhật ở trên. – jthetzel

3

Trong trường hợp này, bạn có thể thay thế textConnection(txt) bằng tên tệp của mình, nhưng về cơ bản bạn có thể tạo mã hoặc chức năng xung quanh strsplit. Ở đây tôi giả sử bạn có một dòng tiêu đề, nhưng bạn tất nhiên có thể đưa ra định nghĩa một đối số header và khái quát hóa việc tạo ra các khung dữ liệu dựa trên các chức năng dưới đây:

> read.multisep <- function(File,sep) { 
+ Lines <- readLines(File) 
+ Matrix <- do.call(rbind,strsplit(Lines,sep,fixed=TRUE)) 
+ DataFrame <- structure(data.frame(Matrix[-1,]),names=Matrix[1,]) ## assuming header is present 
+ DataFrame[] <- lapply(DataFrame,type.convert)     ## automatically convert modes 
+ DataFrame 
+ } 
> 
> example <- "a#*&b#*&c 
+ 1#*&2#*&3 
+ 4#*&5#*&6" 
> 
> read.multisep(textConnection(example),sep="#*&") 
    a b c 
1 1 2 3 
2 4 5 6 
+0

read.multisep hoạt động tốt cho tôi ~! Cảm ơn @jthetzel – RobinMin

Các vấn đề liên quan