2016-01-28 28 views
5

Tôi có một cột chứa đầy các tên cột khác. Tôi muốn có được giá trị trong mỗi tên cột.Sử dụng chuỗi để chọn cột cho mỗi hàng trong dplyr (hoặc cơ sở R)

# three columns with values and one "key" column 
library(dplyr) 
data = data.frame(
    x = runif(10), 
    y = runif(10), 
    z = runif(10), 
    key = sample(c('x', 'y', 'z'), 10, replace=TRUE) 
) 

# now get the value named in 'key' 
data = data %>% mutate(value = VALUE_AT_COLUMN(key)) 

Tôi khá chắc chắn câu trả lời có liên quan đến phiên bản eval lười biếng, nhưng tôi không thể cho cuộc sống của tôi tìm ra.

Mọi trợ giúp sẽ được đánh giá cao.

+1

Bạn cũng có thể thử 'dữ liệu [c (" x "," y "," z ")] [cbind (seq_len (nrow (dữ liệu)), khớp (dữ liệu $ key, tên (dữ liệu))) ] 'để tránh nhóm theo từng hàng (với, có lẽ thấp hơn, chi phí của một chuyển đổi trung gian thành" ma trận "). –

+0

@alexis_laz Tôi thích một cách tiếp cận mở rộng hơn mà không yêu cầu liệt kê mọi cột. – sharoz

+1

Tùy thuộc vào cách các cột của bạn được sắp xếp, cần có nhiều cách để lập trình chương trình giải nén các cột cần thiết; 'dữ liệu [1: 3]', 'dữ liệu [duy nhất (dữ liệu $ key)]', 'dữ liệu [! tên (dữ liệu)% trong%" khóa "]' etc –

Trả lời

5

Dưới đây là một giải pháp cơ sở R:

data$value = diag(as.matrix(data[,data$key])) 
+1

Thú vị, mặc dù tôi đoán đây không phải là bộ nhớ hiệu quả chút nào. –

+2

Không! Có thể có một phương pháp cơ sở hiệu quả hơn bộ nhớ, nhưng nếu bạn đang đi cho hiệu suất thì bạn nên tìm đến 'data.table' hoặc' dplyr'. Nếu bạn không muốn tải thêm gói và dữ liệu của bạn không lớn, thì điều này sẽ hoạt động. –

6

Chúng tôi có thể thử data.table. Chuyển đổi 'data.frame' thành 'data.table' (setDT(data)), được nhóm theo chuỗi các hàng, chúng tôi sử dụng .SD để đặt các cột được chỉ định bằng 'khóa'.

library(data.table) 
setDT(data)[, .SD[, key[[1L]], with=FALSE] ,1:nrow(data)] 

Hoặc tùy chọn khác là get sau khi chuyển đổi các 'chìa khóa' để character lớp (vì nó factor) sau khi nhóm bởi chuỗi các dòng như trong trường hợp trước đó.

setDT(data)[, get(as.character(key)), 1:nrow(data)] 

Đây là một lựa chọn với do

library(dplyr) 
data %>% 
    group_by(rn = row_number()) %>% 
    do(data.frame(., value= .[[.$key]])) 
+0

Tôi có thể thực hiện việc này bằng các thư viện khác, nhưng tôi đang cố gắng tránh nhập thư viện khung dữ liệu khác – sharoz

+0

@sharoz Có thể với 'dplyr' bằng' do', – akrun

+2

Bạn có thể đăng câu trả lời đó không? – sharoz

4

Nó chắc chắn cảm thấy như có phải là một giải pháp cơ sở R để này, nhưng tốt nhất tôi có thể làm là với tidyr, trước tiên chuyển đổi dữ liệu ở dạng rộng, sau đó lọc chỉ những quan sát phù hợp với khóa mong muốn.

data %>% 
    add_rownames("index") %>% 
    gather(var, value, -index, -key) %>% 
    filter(key == var) 

Một giải pháp R cơ sở mà hầu hết các công trình:

data[cbind(seq_along(data$key), data$key)] 

Đối với các dữ liệu nhất định, nó không hoạt động, nhưng bởi vì nó sử dụng một ma trận, nó có hai vấn đề nghiêm trọng. Một là thứ tự của yếu tố quan trọng, bởi vì nó chỉ co giật mà ra, và chọn cột theo cấp độ yếu tố, không phải bởi tên cột. Cách khác là kết quả đầu ra là character, không phải là numeric, bởi vì trong chuyển đổi thành ma trận, loại character được chọn vì cột key. Vấn đề chính là không có tương tự data.frame với hành vi ma trận của

Khi lập chỉ mục mảng bằng '[' một đối số 'i' có thể là ma trận với nhiều cột có kích thước 'x' ; kết quả sau đó là một vectơ với các phần tử tương ứng với các tập hợp các chỉ số trong mỗi hàng của 'i'.

Vì những vấn đề này, tôi có thể đi với giải pháp tidyr, vì thực tế là các cột có thể lựa chọn có nghĩa là chúng có thể đại diện cho các quan sát khác nhau cho cùng một đơn vị quan sát được.

5

Đối với một ký ức giải pháp hiệu quả và nhanh chóng, bạn nên cập nhật dữ liệu ban đầu của bạn.bảng bằng cách thực hiện một tham gia như sau:

data[.(key2 = unique(key)), val := get(key2), on=c(key="key2"), by=.EACHI][] 

Đối với mỗi key2 các hàng tương ứng trong data$key được tính toán. Những hàng này được cập nhật với các giá trị từ cột được chứa trong key2. Ví dụ: key2="x" đối sánh với các hàng 1,2,6,8,10. Giá trị tương ứng của data$xdata$x[c(1,2,6,8,10)]. by=.EACHI đảm bảo biểu thức get(key2) được thực hiện cho mỗi giá trị key2.

Vì thao tác này chỉ được thực hiện trên các giá trị duy nhất nên nhanh hơn đáng kể so với chạy hàng thông minh. Và kể từ khi data.table được cập nhật bằng cách tham chiếu, nó nên được khá bộ nhớ hiệu quả (và góp phần vào tốc độ là tốt).

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