2012-09-17 49 views
5

Tôi đã có một khung dữ liệu 1000 x 100000 lớn như sau để mã hóa thành các giá trị số.ghi lại dữ liệu trong r

myd <- data.frame (v1 = sample (c("AA", "AB", "BB", NA), 10, replace = T), 
        v2 = sample (c("CC", "CG", "GG", NA), 10, replace = T), 
        v3 = sample (c("AA", "AT", "TT", NA) , 10, replace = T), 
        v4 = sample (c("AA", "AT", "TT", NA) , 10, replace = T), 
        v5 = sample (c("CC", "CA", "AA", NA) , 10, replace = T) 
        ) 
myd 
    v1 v2 v3 v4 v5 
1 AB CC <NA> <NA> AA 
2 AB CG TT TT AA 
3 AA GG AT AT CA 
4 <NA> <NA> <NA> AT <NA> 
5 AA <NA> AA <NA> CA 
6 BB <NA> TT TT CC 
7 AA GG AA AT CA 
8 <NA> GG <NA> AT CA 
9 AA <NA> AT <NA> CC 
10 AA GG TT AA CC 

Mỗi biến có khả năng bốn giá trị duy nhất.

unique(myd$v1) 

[1] AB AA <NA> BB 
Levels: AA AB BB 

unique(myd$v2) 

[1] CC CG GG <NA> 
    Levels: CC CG GG 

Giá trị duy nhất như vậy có thể là bất kỳ kết hợp nào, tuy nhiên bao gồm hai bảng chữ cái (ngoại trừ NA). Ví dụ "A", "B" trong trường hợp đầu tiên sẽ kết hợp "AA", "AB", "BB". Mã số cho các giá trị này sẽ là 1, 0, -1 tương ứng. Tương tự cho bảng chữ cái chữ cái thứ hai "C", "G" tạo "CC", "CG", "GG", do đó các mã số sẽ là 1, 0, -1 tương ứng. Vì vậy, các myd trên cần phải được recoded để:

myd 
     v1 v2 v3 v4  v5 
    1 0 1  <NA> <NA> 1 
    2 0 0  -1 -1  1 
    3 1 -1  0 0  0 
    4 <NA> <NA> <NA> 0  <NA> 
    5 1 <NA> 1 < NA>  0 
    6 -1 <NA> -1 -1  -1 
    7 1 -1 1  0  0 
    8 <NA> -1 <NA> 0  0 
    9 1 <NA> 0 <NA>  -1 
    10 1 -1 -1  1  -1 

Trả lời

7

Bạn có thể tận dụng lợi thế của thực tế là dữ liệu của bạn, có chỉ số số bên dưới chúng.

Ví dụ:

> as.numeric(myd$v1) 
[1] 2 2 1 NA 1 3 1 NA 1 1 

Các giá trị số tương ứng với các levels() các yếu tố:

> levels(myd$v1) 
[1] "AA" "AB" "BB" 

Vì vậy, 1 == AA, 2 == AB, 3 == BB ... và vân vân.

Vì vậy, bạn chỉ cần chuyển đổi dữ liệu thành số và áp dụng các phép toán cần thiết để thu thập dữ liệu theo cách bạn muốn. Vì vậy, chúng tôi có thể trừ bằng 2, và sau đó nhân với -1 để có được kết quả của bạn:

(sapply(myd, as.numeric) - 2) * -1 
#----- 
     v1 v2 v3 v4 v5 
[1,] 0 1 NA NA 1 
[2,] 0 0 -1 -1 1 
[3,] 1 -1 0 0 0 
[4,] NA NA NA 0 NA 
[5,] 1 NA 1 NA 0 
[6,] -1 NA -1 -1 -1 
[7,] 1 -1 1 0 0 
[8,] NA -1 NA 0 0 
[9,] 1 NA 0 NA -1 
[10,] 1 -1 -1 1 -1 
+1

Nếu bạn muốn trả về 'data.frame' ed sử dụng 'do.call (data.frame, lapply (myd, function (.x) {- (as.numeric (.x) -2)}))' hoặc 'as.data.frame (lapply (myd, function (.x) {- (as.numeric (.x) -2)})) ' – mnel

8

tôi sẽ đăng một giải pháp khác nhau - (skip to data.table cho cách tiếp cận siêu nhanh!)

Nếu bạn muốn để recode AA, AB, BB, thành 1,0,-1 v.v. bạn có thể sử dụng chỉ mục (cùng với yếu tố đến giải pháp số). Điều này sẽ cho phép bạn có một cách giải mã khác nếu bạn muốn!

tự làm chức năng recode

simple_recode <- function(.x, new_codes){ 
    new_codes[as.numeric(.x)] 
} 

as.data.frame(lapply(myd, simple_recode, new_codes = 1:-1)) 

sử dụng factor

Bạn chỉ có thể relabel các chữ cái bằng cách gọi factor với cấp độ mới như labels

as.data.frame(lapply(myd, factor, labels = 1:-1)) 

data.table cho hiệu quả

Nếu dữ liệu của bạn lớn, thì tôi đề xuất phương pháp data.table sẽ là bộ nhớ và thời gian hiệu quả.

library(data.table) 
DT <- as.data.table(myd) 
as.data.table(DT[,lapply(.SD, simple_recode, new_codes = 1:-1))]) 

Hoặc, hiệu quả hơn

as.data.table(DT[, lapply(.SD, setattr, 'levels', 1:-1)]) 

Hoặc, thậm chí hiệu quả hơn (sửa đổi mức tại chỗ, và tránh as.data.cuộc gọi bảng)

for(name in names(DT)){ 
    setattr(DT[[name]],'levels',1:-1) 
    } 

setattr sửa đổi theo tham chiếu sao cho không sao chép.

cách tiếp cận Hầu như tức thời sử dụng data.table và setattr

Như đã trình bày về vấn đề này lớn dataset

# some big data (100 columns, 1e6 rows) 
big <- replicate(100, factor(sample(c('AA','AB','BB', NA), 1e6, T)), simplify = F) 
bigDT <- as.data.table(big) 

system.time({ 
    for(name in names(big)){ 
    setattr(big[[name]],'levels',1:-1) 
    } 
    })) 

## user system elapsed 
## 0  0  0 
+0

Các nội dung hay. Tôi nghi ngờ rằng chiến lược data.table sẽ nhanh như chớp. –

+0

Tôi chắc chắn rằng sẽ có một cách tiếp cận 'data.table' hiệu quả hơn bằng cách sử dụng' setattr', nếu nó có thể tiếp cận 'bên trong' dữ liệu' data.table'. – mnel

+0

'setattr' có thể tiếp cận bên trong! - data.table thật tuyệt vời. – mnel

4

Nếu bạn thiết lập một bài tập nên LHS có cấu trúc thích hợp, bạn có thể sử dụng giá trị bị ràng buộc ngầm của các yếu tố như chỉ mục vào các giá trị bạn muốn:

> myd[] <- c(-1,0,1)[data.matrix(myd)] 
> myd 
    v1 v2 v3 v4 v5 
1 NA 0 0 0 1 
2 -1 1 0 0 -1 
3 0 NA 1 0 0 
4 NA -1 -1 0 -1 
5 -1 0 1 -1 NA 
6 0 NA 0 1 NA 
7 NA 0 1 NA -1 
8 0 0 0 -1 1 
9 -1 NA 1 -1 NA 
10 0 1 1 NA NA 
Các vấn đề liên quan