2013-04-16 31 views
5

Tôi đã đọc trong một tệp dữ liệu lớn thành R sử dụng lệnh sauSố Unique Obs bởi biến trong một bảng dữ liệu

data <- as.data.set(spss.system.file(paste(path, file, sep = '/'))) 

Các bộ dữ liệu chứa các cột mà không phải thuộc về, và chỉ chứa khoảng trống. Vấn đề này phải làm với R tạo biến mới dựa trên các nhãn biến gắn liền với tệp SPSS (Source).

Rất tiếc, tôi không thể xác định các tùy chọn cần thiết để giải quyết sự cố. Tôi đã thử tất cả: nước ngoài :: read.spss, memisc: spss.system.file, và Hemisc :: spss.get, không có may mắn.

Thay vào đó, tôi muốn đọc trong toàn bộ tập dữ liệu (có cột ma) và xóa các biến không cần thiết theo cách thủ công. Vì các cột ma chỉ chứa các khoảng trắng, nên tôi muốn xóa bất kỳ biến nào từ data.table của tôi, nơi số lượng các quan sát duy nhất bằng một.

Dữ liệu của tôi lớn, do đó chúng được lưu trữ ở định dạng data.table. Tôi muốn xác định một cách dễ dàng để kiểm tra số quan sát duy nhất trong mỗi cột và thả các cột chỉ chứa một quan sát duy nhất.

require(data.table) 

### Create a data.table 
dt <- data.table(a = 1:10, 
       b = letters[1:10], 
       c = rep(1, times = 10)) 

### Create a comparable data.frame 
df <- data.frame(dt) 

### Expected result 
unique(dt$a) 

### Expected result 
length(unique(dt$a)) 

Tuy nhiên, tôi muốn tính số lượng người theo dõi cho tệp dữ liệu lớn, do đó, không nên tham chiếu từng cột theo tên. Tôi không phải là fan của eval (parse()).

### I want to determine the number of unique obs in 
    # each variable, for a large list of vars 
lapply(names(df), function(x) { 
    length(unique(df[, x])) 
}) 

### Unexpected result 
length(unique(dt[, 'a', with = F])) # Returns 1 

Dường như với tôi vấn đề là

dt[, 'a', with = F] 

trả về một đối tượng của lớp "data.table". Nó có ý nghĩa rằng độ dài của đối tượng này là 1, vì nó là một data.table chứa 1 biến. Chúng tôi biết rằng data.frames thực sự chỉ là danh sách các biến và vì vậy trong trường hợp này độ dài của danh sách chỉ là 1.

Đây là mã giả để tôi giải quyết giải pháp, sử dụng cách data.frame:

for (x in names(data)) { 
    unique.obs <- length(unique(data[, x])) 
    if (unique.obs == 1) { 
    data[, x] <- NULL 
    } 
} 

Bất kỳ thông tin chi tiết nào về cách tôi có thể yêu cầu số lượng quan sát một cách hiệu quả hơn theo cột trong data.table sẽ được đánh giá cao. Ngoài ra, nếu bạn có thể giới thiệu cách thả các quan sát nếu chỉ có một quan sát duy nhất trong một data.table sẽ tốt hơn.

Trả lời

7

Cập nhật: uniqueN

Tính đến phiên bản 1.9.6, có phiên bản được tối ưu hóa (được tối ưu hóa) của giải pháp này, chức năng uniqueN. Bây giờ đây là đơn giản như:

dt[ , lapply(.SD, uniqueN)] 

Nếu bạn muốn tìm số giá trị duy nhất trong mỗi cột, một cái gì đó giống như

dt[, lapply(.SD, function(x) length(unique(x)))] 
##  a b c 
## 1: 10 10 1 

Để có được chức năng của bạn để làm việc bạn cần phải sử dụng with=FALSE trong [.data.table, hoặc đơn giản là sử dụng [[ thay vì (đọc fortune(312) cũng ...)

lapply(names(df) function(x) length(unique(dt[, x, with = FALSE]))) 

hoặc

lapply(names(df) function(x) length(unique(dt[[x]]))) 

sẽ làm việc

Trong một bước

dt[,names(dt) := lapply(.SD, function(x) if(length(unique(x)) ==1) {return(NULL)} else{return(x)})] 


# or to avoid calling `.SD` 

dt[, Filter(names(dt), f = function(x) length(unique(dt[[x]]))==1) := NULL] 
+0

1 Như tôi đã nói, tôi có cảm giác rằng tôi có thể đơn giản hóa cách tiếp cận của tôi ... nhưng tôi sẽ không đưa ra giải pháp của bạn. Chết tiệt, đây là gọn gàng ... –

1

Đây là giải pháp cho vấn đề cốt lõi của bạn (Tôi hy vọng tôi đã làm đúng).

require(data.table) 

### Create a data.table 
dt <- data.table(a = 1:10, 
       b = letters[1:10], 
       d1 = "", 
       c = rep(1, times = 10), 
       d2 = "") 
dt 
    a b d1 c d2 
1: 1 a 1 
2: 2 b 1 
3: 3 c 1 
4: 4 d 1 
5: 5 e 1 
6: 6 f 1 
7: 7 g 1 
8: 8 h 1 
9: 9 i 1 
10: 10 j 1 

Trước tiên, tôi giới thiệu hai cột d1d2 không có giá trị gì. Những người bạn muốn xóa, phải không? Nếu có, tôi chỉ xác định các cột đó và chọn tất cả các cột khác trong số dt.

only_space <- function(x) { 
    length(unique(x))==1 && x[1]=="" 
} 
bolCols <- apply(dt, 2, only_space) 
dt[, (1:ncol(dt))[!bolCols], with=FALSE] 

Bằng cách nào đó, tôi có cảm giác rằng bạn tiếp tục có thể đơn giản hóa nó ...

Output:

 a b c 
1: 1 a 1 
2: 2 b 1 
3: 3 c 1 
4: 4 d 1 
5: 5 e 1 
6: 6 f 1 
7: 7 g 1 
8: 8 h 1 
9: 9 i 1 
10: 10 j 1 
3

Các cách tiếp cận trong các câu trả lời khác là tốt. Một cách khác để thêm vào hỗn hợp, chỉ để cho vui:

for (i in names(DT)) if (length(unique(DT[[i]]))==1) DT[,(i):=NULL] 

hoặc nếu có thể có tên cột trùng lặp:

for (i in ncol(DT):1) if (length(unique(DT[[i]]))==1) DT[,(i):=NULL] 

NB: (i) trên LHS của := là một thủ thuật để sử dụng giá trị của i thay vì cột có tên "i".

0

Có một cách dễ dàng để làm điều đó bằng "dplyr" thư viện, và sau đó sử dụng chọn chức năng như sau:

thư viện (dplyr)

newdata < - chọn (old_data, biến đầu tiên, biến thứ hai)

Lưu ý rằng, bạn có thể chọn bao nhiêu biến tùy thích.

Sau đó, bạn sẽ nhận được loại dữ liệu bạn muốn.

Rất cám ơn,

Fadhah

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