2013-02-25 32 views
21

Tôi đã sử dụng chức năng prcomp khi tôi nhận được lỗi nàydiệt các cột liên tục trong R

Error in prcomp.default(x, ...) : 
cannot rescale a constant/zero column to unit variance 

Tôi biết tôi có thể quét dữ liệu của tôi bằng tay nhưng có bất kỳ chức năng hoặc lệnh trong R có thể giúp tôi loại bỏ những biến không đổi? Tôi biết đây là một nhiệm vụ rất đơn giản, nhưng tôi chưa bao giờ gặp bất kỳ chức năng nào thực hiện điều này.

Xin cảm ơn,

+1

Vui lòng đọc nguyên tắc đăng bài và cung cấp mẫu nhỏ, có thể tái sản xuất 'x'. Ngay bây giờ chúng tôi thậm chí không biết nếu 'x' của bạn là số, hãy để một mình một ma trận. Bây giờ, nếu nó là một ma trận, 'y <- x [, sd (x)! = 0]' sẽ đủ. –

+1

Có lẽ không cần thiết nếu bạn đang sử dụng prcomp trên dữ liệu của bạn, nhưng nếu bạn có các loại cột hỗn hợp, một giải pháp đơn giản là 'x [, áp dụng (x, 2, hàm (col) {length (unique (col))> 1 })] ' –

Trả lời

35

Vấn đề ở đây là phương sai cột của bạn bằng 0. Bạn có thể kiểm tra cột của một khung dữ liệu là hằng số theo cách này, ví dụ:

df <- data.frame(x=1:5, y=rep(1,5)) 
df 
# x y 
# 1 1 1 
# 2 2 1 
# 3 3 1 
# 4 4 1 
# 5 5 1 

# Supply names of columns that have 0 variance 
names(df[, sapply(df, function(v) var(v, na.rm=TRUE)==0)]) 
# [1] "y" 

Vì vậy, nếu bạn muốn loại trừ những cột này, bạn có thể sử dụng:

df[,sapply(df, function(v) var(v, na.rm=TRUE)!=0)] 

EDIT: Trong thực tế nó là đơn giản để sử dụng apply thay thế. Một cái gì đó như thế này:

df[,apply(df, 2, var, na.rm=TRUE) != 0] 
+0

Điều này có nhanh hơn (hoặc mạnh hơn) so với giải pháp tối thiểu của tôi trong nhận xét ở trên không? - khác hơn là tôi đang sử dụng một hoạt động chính thức không được chấp thuận với 'sd' :-) –

+1

@CarlWitthoft Vâng, vì lời khuyên khi bạn sử dụng' sd (x) 'là sử dụng' áp dụng (x, 2, sd) ' , Tôi nghĩ rằng nó khá giống nhau, nếu bạn làm theo lời khuyên :) – juba

+0

câu trả lời tuyệt vời, nhờ – zach

9

Tôi đoán đây Q & A là một kết quả tìm kiếm Google phổ biến nhưng câu trả lời là một chút chậm đối với một ma trận lớn, cộng với tôi không có đủ uy tín để nhận xét về câu trả lời đầu tiên. Vì vậy, tôi đăng câu trả lời mới cho câu hỏi.

Đối với mỗi cột của một ma trận lớn, kiểm tra xem mức tối đa bằng mức tối thiểu có đủ hay không.

df[,!apply(df, MARGIN = 2, function(x) max(x, na.rm = TRUE) == min(x, na.rm = TRUE))] 

Đây là thử nghiệm. Hơn 90% thời gian được giảm so với câu trả lời đầu tiên. Nó cũng nhanh hơn câu trả lời từ bình luận thứ hai về câu hỏi.

ncol = 1000000 
nrow = 10 
df <- matrix(sample(1:(ncol*nrow),ncol*nrow,replace = FALSE), ncol = ncol) 
df[,sample(1:ncol,70,replace = FALSE)] <- rep(1,times = nrow) # df is a large matrix 

time1 <- system.time(df1 <- df[,apply(df, 2, var, na.rm=TRUE) != 0]) # the first method 
time2 <- system.time(df2 <- df[,!apply(df, MARGIN = 2, function(x) max(x, na.rm = TRUE) == min(x, na.rm = TRUE))]) # my method 
time3 <- system.time(df3 <- df[,apply(df, 2, function(col) { length(unique(col)) > 1 })]) # Keith's method 

time1 
# user system elapsed 
# 22.267 0.194 22.626 
time2 
# user system elapsed 
# 2.073 0.077 2.155 
time3 
# user system elapsed 
# 6.702 0.060 6.790 
all.equal(df1, df2) 
# [1] TRUE 
all.equal(df3, df2) 
# [1] TRUE 
+1

Tôi đọc lại và thấy nhanh hơn 15% khi sử dụng tất cả (x == x [1], na.rm = TRUE) thay vì tính toán max và min. – DavidR

+0

Vị trí (hàm (x)! Is.na (x), x) cho biết vị trí chỉ mục của phần tử non-na đầu tiên, và điều này dành nhiều thời gian hơn nếu x có một số giá trị na. – raymkchow

1

Kể từ Q này & A là một kết quả tìm kiếm Google phổ biến nhưng câu trả lời là một chút chậm đối với một ma trận lớn và phiên bản @raymkchow chậm bằng NA tôi đề xuất một phiên bản mới sử dụng tìm kiếm theo cấp số nhân và data.table điện.

Chức năng này tôi đã triển khai trong gói dataPreparation.

đầu tiên xây dựng một data.table dụ, với những đường nét hơn cột (mà thường là trường hợp) và 10% của NAS

ncol = 1000 
nrow = 100000 
df <- matrix(sample(1:(ncol*nrow),ncol*nrow,replace = FALSE), ncol = ncol) 
df <- apply (df, 2, function(x) {x[sample(c(1:nrow), floor(nrow/10))] <- NA; x}) # Add 10% of NAs 
df[,sample(1:ncol,70,replace = FALSE)] <- rep(1,times = nrow) # df is a large matrix 
df <- as.data.table(df) 

Sau đó, điểm chuẩn tất cả các phương pháp:

time1 <- system.time(df1 <- df[,apply(df, 2, var, na.rm=TRUE) != 0, with = F]) # the first method 
time2 <- system.time(df2 <- df[,!apply(df, MARGIN = 2, function(x) max(x, na.rm = TRUE) == min(x, na.rm = TRUE)), with = F]) # raymkchow 
time3 <- system.time(df3 <- df[,apply(df, 2, function(col) { length(unique(col)) > 1 }), with = F]) # Keith's method 
time4 <- system.time(df4 <- df[,-whichAreConstant(df, verbose=FALSE)]) # My method 

Kết quả như sau:

time1 # Variance approch 
# user system elapsed 
# 2.55 1.45 4.07 
time2 # Min = max approach 
# user system elapsed 
# 2.72  1.5 4.22 
time3 # length(unique()) approach 
# user system elapsed 
# 6.7 2.75 9.53 
time4 # Exponential search approach 
# user system elapsed 
# 0.39 0.07 0.45 
all.equal(df1, df2) 
# [1] TRUE 
all.equal(df3, df2) 
# [1] TRUE 
all.equal(df4, df2) 
# [1] TRUE 

dataPreparation:whichAreConstant nhanh hơn 10 lần so với o phương pháp tiếp cận.

Cộng với các hàng khác, bạn có nhiều đường liên kết hơn để sử dụng.

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