2012-05-16 28 views
6

Tôi có một câu hỏi liên quan đến hàm colMeans. Có một phiên bản này sẽ không trả về lỗi khi nó chạy vào một cột có chiều dài không? Ví dụcolMeans hoạt động trong R và gặp sự cố với các cột có kích thước 1

temp<-cbind(c(2,2),c(3,4)) 
colMeans(temp) 

[1] 2.0 3.5 

Nhưng đối với này một

temp2<-c(2,2) 
colMeans(temp2) 

Error in colMeans(temp2) : 
'x' must be an array of at least two dimensions 

Nhưng, nếu tôi áp dụng các chức năng có nghĩa là cho mỗi cột nó đúng đi lên với giá trị 2 và 2.

Tôi đã viết một chức năng để làm điều này

testfun<-function(i,x){ 
mean(x[,i]) 
} 
sapply(1:ncol(x),testfun,x) 

mang lại kết quả tương tự như colMeans.
Tôi đã nghe nói rằng colMeans được cho là nhanh hơn nhiều so với phương pháp này. Vì vậy, có một phiên bản của colMeans sẽ hoạt động khi cột của tôi có kích thước 1.

Trả lời

7

Như @ Paul chỉ ra, colMeans hy vọng "một mảng của hai hay nhiều kích thước" cho x đối số của nó (từ ?colMeans). Nhưng temp2 không phải là một mảng

is.array(temp2) 
# [1] FALSE 

temp2 thể được làm thành một mảng:

(tempArray <- array(temp2, dim = c(1, 2))) 
#  [,1] [,2] 
# [1,] 2 2 

colMeans(tempArray) 
# [1] 2 2 

lẽ temp2 đến từ Subsetting một mảng, chẳng hạn như

array(temp2, dim = c(2, 2))[1, ] 

Nhưng điều này không phải là một mảng. Để giữ nó như một mảng, thêm drop = FALSE bên trong dấu ngoặc:

array(temp2, dim = c(2, 2))[1, , drop = FALSE] 
#  [,1] [,2] 
# [1,] 2 2 

Sau đó, bạn có thể sử dụng colMeans trên mảng subsetted.

4

Chức năng colMeans có nghĩa là cho mảng n chiều. Khi cột của bạn có kích thước 1 (1 colum hoặc 1 hàng ??), bạn có một véc-tơ hiệu quả. Trên một véc tơ, chỉ sử dụng mean là tốt. Xét về tốc độ, tính toán giá trị trung bình của một triệu số rất nhanh:

> system.time(mean(runif(10e5))) 
    user system elapsed 
    0.038 0.000 0.038 
2

@PaulHiemstra và @BenBarnes cung cấp câu trả lời đúng. Tôi chỉ muốn thêm vào những lời giải thích của họ.

Vectors vs mảng

Vectors là những cấu trúc dữ liệu cơ bản trong R. Hầu như tất cả mọi thứ được nội biểu diễn dưới dạng một vector, thậm chí danh sách (với ngoại lệ của một loại đặc biệt của danh sách, chấm danh sách cặp, xem ?list). Mảng chỉ đơn giản là vectơ với thuộc tính được đính kèm, thuộc tính dim, mô tả kích thước của đối tượng. Hãy xem xét những điều sau đây:

v <- c(1:10) 
a <- array(v, dim = c(5, 2)) 
length(v) # 10 
length(a) # 10 
attributes(v) # NULL 
attributes(a) # $dim 10 1 
is.vector(v) # TRUE 
is.array(v) # FALSE 
is.vector(a) # FALSE 
is.array(a) # TRUE 

Cả va là chiều dài 10. Sự khác biệt duy nhất là a có thuộc tính dim được đính kèm với nó. Do thuộc tính được thêm vào này, R xử lý a bên ngoài dưới dạng mảng thay vì vectơ.Sửa đổi chỉ là thuộc tính dim có thể thay đổi đại diện bên ngoài R của một đối tượng từ mảng vector và trở lại:

attr(a, "dim") <- NULL 
is.vector(a) # TRUE 
is.array(a) # FALSE 
attr(v, "dim") <- c(5, 2) 
is.vector(v) # FALSE 
is.array(v) # TRUE 

Trong ví dụ của bạn, temp2 là một đối tượng vector, do đó thiếu một thuộc tính dim. colMeans đang mong đợi đối tượng array có thuộc tính dim có độ dài ít nhất là 2 (hai chiều). Bạn có thể dễ dàng chuyển đổi temp2 đến một mảng hai chiều với một cột duy nhất:

temp3 <- array(temp2, dim = c(length(temp2), 1)) 
# or: 
temp4 <- temp2 
attr(temp4, "dim") <- c(length(temp2), 1) 
is.array(temp2) # FALSE 
is.array(temp3) # TRUE 
is.array(temp4) # TRUE 

colMeans() vs nghĩa()

@PaulHiemstra là đúng, thay vì chuyển đổi một vector để một cột duy nhất cho colMeans(), việc sử dụng mean() phổ biến hơn trên một vectơ. Tuy nhiên, bạn đúng là colMeans() nhanh hơn. Tôi tin rằng điều này là bởi vì nó kiểm tra một chút ít hơn cho dữ liệu được định dạng tốt, nhưng chúng tôi sẽ phải xem xét mã C nội bộ để chắc chắn. Hãy xem xét ví dụ sau:

# Create vector "v" and array "a" 
n <- 10e7 
set.seed(123) # Set random number seed to ensure "v" and "a[,1]" are equal 
v <- runif(n) 
set.seed(123) # Set random number seed to ensure "v" and "a[,1]" are equal 
a <- array(runif(n), dim=c(n, 1)) 

# Test that "v" and "a[,1]" are equal 
all.equal(v, a[,1]) # TRUE 

# Functions to compare 
f1 <- function(x = v){mean(x)} # Using mean on vector 
f2 <- function(x = a){mean(x)} # Using mean on array 
f3 <- function(x = a){colMeans(x)} # Using colMeans on array 

# Compare elapsed time 
system.time(f1()) # elapsed time = 0.344 
system.time(f2()) # elapsed time = 0.366 
system.time(f3()) # elapsed time = 0.166 

colMeans() trên mảng là nhanh hơn so với mean() trên hoặc là một vector hoặc một mảng. Tuy nhiên, phần lớn thời gian tăng tốc này sẽ không đáng kể. Tôi thấy rằng tự nhiên hơn khi chỉ sử dụng mean() trên một mảng vectơ hoặc một cột. Tuy nhiên, nếu bạn là một con quỷ tốc độ thực sự bạn có thể ngủ ngon hơn vào ban đêm khi biết rằng bạn đang tiết kiệm vài trăm mili giây thời gian xử lý bằng cách sử dụng colMeans() trên các mảng cột đơn thay thế.

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