2016-04-20 11 views
5

Tôi muốn kiểm tra tất cả các quan sát đã đạt đến một số nút trong cây quyết định rpart. Ví dụ, trong đoạn mã sau:Lấy các quan sát trong nút của rpart (ví dụ: CART)

fit <- rpart(Kyphosis ~ Age + Start, data = kyphosis) 
fit 

n= 81 

node), split, n, loss, yval, (yprob) 
     * denotes terminal node 

1) root 81 17 absent (0.79.20987654) 
    2) Start>=8.5 62 6 absent (0.90322581 0.09677419) 
    4) Start>=14.5 29 0 absent (1.00000000 0.00000000) * 
    5) Start< 14.5 33 6 absent (0.81818182 0.18181818) 
     10) Age< 55 12 0 absent (1.00000000 0.00000000) * 
     11) Age>=55 21 6 absent (0.71428571 0.28571429) 
     22) Age>=111 14 2 absent (0.85714286 0.14285714) * 
     23) Age< 111 7 3 present (0.42857143 0.57142857) * 
    3) Start< 8.5 19 8 present (0.42105263 0.57894737) * 

Tôi muốn xem tất cả các quan sát trong nút (5) (nghĩa là .: Cơ sở 33 quan sát mà Bắt đầu> = 8,5 & Bắt đầu < 14,5). Rõ ràng tôi có thể tự nhận được chúng. Nhưng tôi muốn có một số chức năng như (nói) "get_node_date". Tôi chỉ có thể chạy get_node_date (5) - và nhận được các quan sát có liên quan.

Bất kỳ đề xuất nào về cách thực hiện việc này?

Trả lời

1

Có vẻ là không có chức năng như vậy cho phép một chiết xuất của các quan sát từ một nút cụ thể. Tôi sẽ giải quyết nó như sau: đầu tiên xác định quy tắc/s là/được sử dụng cho các nút bạn đang insterested in Bạn có thể sử dụng path.rpart cho nó. Sau đó, bạn có thể áp dụng các quy tắc/s sau khi khác để trích xuất các quan sát.

Cách tiếp cận này là một hàm:

get_node_date <- function(tree = fit, node = 5){ 
    rule <- path.rpart(tree, node) 
    rule_2 <- sapply(rule[[1]][-1], function(x) strsplit(x, '(?<=[><=])(?=[^><=])|(?<=[^><=])(?=[><=])', perl = TRUE)) 
    ind <- apply(do.call(cbind, lapply(rule_2, function(x) eval(call(x[2], kyphosis[,x[1]], as.numeric(x[3]))))), 1, all) 
    kyphosis[ind,] 
    } 

Đối với nút 5 bạn nhận được:

get_node_date() 

node number: 5 
    root 
    Start>=8.5 
    Start< 14.5 
    Kyphosis Age Number Start 
2 absent 158  3 14 
10 present 59  6 12 
11 present 82  5 14 
14 absent 1  4 12 
18 absent 175  5 13 
20 absent 27  4  9 
23 present 96  3 12 
26 absent 9  5 13 
28 absent 100  3 14 
32 absent 125  2 11 
33 absent 130  5 13 
35 absent 140  5 11 
37 absent 1  3  9 
39 absent 20  6  9 
40 present 91  5 12 
42 absent 35  3 13 
46 present 139  3 10 
48 absent 131  5 13 
50 absent 177  2 14 
51 absent 68  5 10 
57 absent 2  3 13 
59 absent 51  7  9 
60 absent 102  3 13 
66 absent 17  4 10 
68 absent 159  4 13 
69 absent 18  4 11 
71 absent 158  5 14 
72 absent 127  4 12 
74 absent 206  4 10 
77 present 157  3 13 
78 absent 26  7 13 
79 absent 120  2 13 
81 absent 36  4 13 
1

rpart trả về yếu tố rpart.object chứa thông tin bạn cần:

require(rpart) 
fit2 <- rpart(Kyphosis ~ Age + Start, data = kyphosis) 
fit2 

get_node_date <-function(nodeId,fit) 
{ 
    fit$frame[toString(nodeId),"n"] 
} 


for (i in c(1,2,4,5,10,11,22,23,3)) 
    cat(get_node_date(i,fit2),"\n") 
+1

Bạn không nhận được những quan sát qua chuyện này, nhưng chỉ có số abservations mà rơi vào một thể loại – DatamineR

+1

bạn nói đúng, hiểu sai câu hỏi –

1

Gói partykit cũng cung cấp một giải pháp đóng hộp cho việc này. Bạn chỉ cần chuyển đổi đối tượng rpart thành lớp party để sử dụng giao diện thống nhất của nó để xử lý cây. Và sau đó bạn có thể sử dụng hàm data_party().

Sử dụng fit từ câu hỏi và đã nạp library("partykit") đầu tiên bạn có thể ép buộc các rpart cây để party:

pfit <- as.party(fit) 
plot(pfit) 

full pfit tree

Chỉ có hai phiền hà nhỏ để trích xuất dữ liệu theo cách của bạn muốn: (1) Các model.frame() từ phù hợp ban đầu là luôn luôn giảm trong cưỡng chế và cần phải được reattached bằng tay. (2) Một lược đồ đánh số khác nhau được sử dụng cho các nút. Bạn muốn nút 4 (thay vì 5) bây giờ.

pfit$data <- model.frame(fit) 
data4 <- data_party(pfit, 4) 
dim(data4) 
## [1] 33 5 
head(data4) 
## Kyphosis Age Start (fitted) (response) 
## 2 absent 158 14  7  absent 
## 10 present 59 12  8 present 
## 11 present 82 14  8 present 
## 14 absent 1 12  5  absent 
## 18 absent 175 13  7  absent 
## 20 absent 27  9  5  absent 

tuyến đường khác là tập hợp con các cây con bắt đầu từ nút 4 và sau đó lấy dữ liệu từ:

pfit4 <- pfit[4] 
plot(pfit4) 

subtree of pfit from node 4

Sau đó data_party(pfit4) mang đến cho bạn giống như data4 trên. Và pfit4$data cung cấp cho bạn dữ liệu mà không cần nút (fitted) và được dự đoán là (response).

+0

nếu bạn sử dụng 'data ptree $ <- model.frame (eval (tree $ call $ data)) 'các biến không được sử dụng trong công thức sẽ không bị xóa – rawr

+0

Đúng ... nhưng chỉ khi' dữ liệu' chứa tất cả các biến trong 'công thức' mà không nhất thiết phải là trường hợp. Với 'model.frame()', bạn cũng nhận được các biến được chuyển đổi, ví dụ, 'log()', 'Surv()' hoặc 'factor()' phiên bản của các biến thường được tạo ra khi đang bay. –

+0

BTW: Sự cưỡng chế 'as.party()' đối với các đối tượng 'rpart' bây giờ _ giữ dữ liệu theo mặc định! Vì vậy, bạn có thể làm 'as.party (fit, data = TRUE)' (là mặc định mới) hoặc 'as.party (fit, data = FALSE)' (tương ứng với hành vi cũ). –

1

Tuy nhiên, cách khác, điều này hoạt động bằng cách tìm tất cả các nút đầu cuối của bất kỳ nút cụ thể nào và trả lại tập con dữ liệu được sử dụng trong cuộc gọi.

fit <- rpart(Kyphosis ~ Age + Start, data = kyphosis) 

head(subset.rpart(fit, 5)) 
# Kyphosis Age Number Start 
# 2 absent 158  3 14 
# 10 present 59  6 12 
# 11 present 82  5 14 
# 14 absent 1  4 12 
# 18 absent 175  5 13 
# 20 absent 27  4  9 


subset.rpart <- function(tree, node = 1L) { 
    data <- eval(tree$call$data, parent.frame(1L)) 
    wh <- sapply(as.integer(rownames(tree$frame)), parent) 
    wh <- unique(unlist(wh[sapply(wh, function(x) node %in% x)])) 
    data[rownames(tree$frame)[tree$where] %in% wh[wh >= node], ] 
} 

parent <- function(x) { 
    if (x[1] != 1) 
    c(Recall(if (x %% 2 == 0L) x/2 else (x - 1)/2), x) else x 
} 
Các vấn đề liên quan