2014-05-02 56 views
21

xem xét như sau:Sự khác nhau giữa 'tên (df [1]) <- `và` tên (df) [1] <- `

df <- data.frame(a = 1, b = 2, c = 3) 
names(df[1]) <- "d" ## First method 
## a b c 
##1 1 2 3 

names(df)[1] <- "d" ## Second method 
## d b c 
##1 1 2 3 

Cả hai phương pháp này không trả về một lỗi, nhưng đầu tiên đã không thay đổi tên cột, trong khi thứ hai đã làm.

Tôi nghĩ rằng nó có liên quan đến thực tế là tôi chỉ hoạt động trên một tập hợp con của df, nhưng tại sao, ví dụ, sau đây hoạt động tốt sau đó?

df[1] <- 2 
## a b c 
##1 2 2 3 
+1

Tôi thích câu trả lời của Joshua ở đây: http://stackoverflow.com/a/10449502/1270695. Anh ta nói đó là phép thuật. – A5C1D2H2I1M1N2O1R2T1

+0

Câu trả lời của Joshua đề cập đến ví dụ thứ hai, không phải là một ví dụ không làm bất cứ điều gì ... –

+2

Ohboyohboy, bạn đang ở trong một điều trị: đọc này (in) chuyên khảo nổi tiếng - http: //www.burns-stat .com/pages/Tutor/R_inferno.pdf –

Trả lời

26

Điều tôi nghĩ đang xảy ra là việc thay thế vào khung dữ liệu sẽ bỏ qua các thuộc tính của khung dữ liệu được vẽ. Tôi không chắc chắn 100% về điều này, nhưng các thí nghiệm sau đây xuất hiện để trở lại nó lên:

df <- data.frame(a = 1:3, b = 5:7) 
# a b 
# 1 1 5 
# 2 2 6 
# 3 3 7 

df2 <- data.frame(c = 10:12) 
# c 
# 1 10 
# 2 11 
# 3 12 

df[1] <- df2[1] # in this case `df[1] <- df2` is equivalent 

nào sản xuất:

# a b 
# 1 10 5 
# 2 11 6 
# 3 12 7 

Thông báo như thế nào các giá trị thay đổi cho df, nhưng không có tên. Về cơ bản, toán tử thay thế `[<-` chỉ thay thế các giá trị. Đây là lý do tại sao tên không được cập nhật. Tôi tin rằng điều này giải thích tất cả các vấn đề.

Trong kịch bản:

names(df[2]) <- "x" 

Bạn có thể nghĩ đến việc chuyển nhượng như sau (đây là một việc đơn giản hóa, xem cuối bài để xem chi tiết hơn):

tmp <- df[2] 
# b 
# 1 5 
# 2 6 
# 3 7 

names(tmp) <- "x" 
# x 
# 1 5 
# 2 6 
# 3 7 

df[2] <- tmp # `tmp` has "x" for names, but it is ignored! 
# a b 
# 1 10 5 
# 2 11 6 
# 3 12 7 

Bước cuối cùng trong số đó là một nhiệm vụ với `[<-`, không tôn trọng thuộc tính tên của RHS.

Nhưng trong kịch bản:

names(df)[2] <- "x" 

bạn có thể nghĩ đến việc chuyển nhượng như (một lần nữa, đơn giản hóa):

tmp <- names(df) 
# [1] "a" "b" 

tmp[2] <- "x" 
# [1] "a" "x" 

names(df) <- tmp 
# a x 
# 1 10 5 
# 2 11 6 
# 3 12 7 

Chú ý cách chúng tôi trực tiếp gán cho names, thay vì gán cho df bỏ qua các thuộc tính.

df[2] <- 2 

công trình vì chúng ta đang gán trực tiếp đến giá trị, không phải là thuộc tính, vì vậy không có vấn đề ở đây.


EDIT: dựa trên một số bình luận từ @ AriB.Friedman, đây là một phiên bản phức tạp hơn những gì tôi nghĩ đang xảy ra (lưu ý tôi bỏ qua công văn S3 để `[.data.frame` vv, Cho rõ ràng):

Phiên bản 1 names(df[2]) <- "x" dịch để:

df <- `[<-`(
    df, 2, 
    value=`names<-`( # `names<-` here returns a re-named one column data frame 
    `[`(df, 2),  
    value="x" 
)) 

Phiên bản 2 names(df)[2] <- "x" dịch để:

df <- `names<-`(
    df, 
    `[<-`(
    names(df), 2, "x" 
)) 

Ngoài ra, hóa ra đây là "tài liệu" trong R Inferno Mục 8.2.34 (Cảm ơn @Frank):

right <- wrong <- c(a=1, b=2) 
names(wrong[1]) <- 'changed' 
wrong 
# a b 
# 1 2 
names(right)[1] <- 'changed' 
right 
# changed b 
# 1 2 
Các vấn đề liên quan