2011-02-09 57 views
23

Tôi có một khung dữ liệu mà tôi muốn thêm một hàng bổ sung tổng các giá trị cho các cột. Ví dụ, Hãy nói rằng tôi có dữ liệu này:Làm cách nào để thêm hàng vào khung dữ liệu có tổng số?

x <- data.frame(Language=c("C++", "Java", "Python"), 
       Files=c(4009, 210, 35), 
       LOC=c(15328,876, 200), 
       stringsAsFactors=FALSE)  

dữ liệu trông như thế này:

Language Files LOC 
1  C++ 4009 15328 
2  Java 210 876 
3 Python 35 200 

bản năng của tôi là để làm điều này:

y <- rbind(x, c("Total", colSums(x[,2:3]))) 

Và công trình này, nó tính toán tổng số:

> y 
    Language Files LOC 
1  C++ 4009 15328 
2  Java 210 876 
3 Python 35 200 
4 Total 4254 16404 

Prob lem đang là Files and cột LỘC đều được chuyển đổi thành các chuỗi:

> y$LOC 
[1] "15328" "876" "200" "16404" 

Tôi hiểu rằng điều này xảy ra bởi vì tôi đã tạo ra một vector c("Total", colSums(x[,2:3]) với đầu vào có cả số và chuỗi, và nó chuyển đổi tất cả các yếu tố để một loại phổ biến để tất cả các phần tử vectơ giống nhau. Sau đó, điều tương tự cũng xảy ra với các cột Tệp và LOC.

Cách nào tốt hơn để thực hiện việc này?

Trả lời

18

Bạn có cần cột Ngôn ngữ trong dữ liệu của mình hay không thích hợp hơn khi nghĩ cột đó là row.names? Điều đó sẽ thay đổi data.frame của bạn từ 4 quan sát của 3 biến thành 4 quan sát của 2 biến (Files & LOC).

x <- data.frame(Files=c(4009, 210, 35), LOC=c(15328,876, 200), row.names=c("C++", "Java", "Python"), stringsAsFactors=F)  
x["Total" ,] <- colSums(x) 


> x 
     Files LOC 
C++  4009 15328 
Java  210 876 
Python 35 200 
Total 4254 16404 
+12

Cá nhân, tôi không khuyên bạn nên lưu trữ dữ liệu trong tên miền - đó là những biến số dành cho! – hadley

+1

Nói chung, tôi đồng ý. Tôi cũng có xu hướng làm theo lời khuyên của @ csgillespie về việc không trộn dữ liệu thô và thống kê tóm tắt trong cùng một đối tượng. Như OP chỉ ra tuy nhiên, nó không thực sự là một vấn đề trong trường hợp này kể từ khi câu hỏi xoay quanh việc trình bày dữ liệu, không phải bất kỳ phân tích thêm. – Chase

+3

Tương đương tidyverse là gì? – thadk

19

Đây là cách giúp bạn đạt được những gì bạn muốn, nhưng có thể là giải pháp thanh lịch hơn.

rbind(x, data.frame(Language="Total",t(colSums(x[,-1])))) 

Đối với hồ sơ, tôi thích Chase của câu trả lời nếu bạn không hoàn toàn cần cột Language.

4

Nếu (1) chúng tôi không cần tiêu đề "Language" trên cột đầu tiên thì chúng tôi có thể đại diện cho nó bằng cách sử dụng tên hàng và nếu (2) được gắn nhãn hàng cuối cùng là "Sum" thay vì "Total" thì chúng ta có thể sử dụng addmargins như thế này:

rownames(x) <- x$Language 
addmargins(as.table(as.matrix(x[-1])), 1) 

hiến:

 Files LOC 
C++  4009 15328 
Java  210 876 
Python 35 200 
Sum  4254 16404 

Nếu chúng ta làm muốn cột đầu tiên dán nhãn "Language" và tổng hàng dán nhãn "Total" sau đó của nó một chút lo nger:

rownames(x) <- x$Language 
Total <- sum 
xa <- addmargins(as.table(as.matrix(x[-1])), 1, FUN = Total) 
data.frame(Language = rownames(xa), as.matrix(xa[]), row.names = NULL) 

cho:

Language Files LOC 
1  C++ 4009 15328 
2  Java 210 876 
3 Python 35 200 
4 Total 4254 16404 
1

Bạn có chắc chắn bạn thực sự muốn có những tổng số cột trong khung dữ liệu của bạn? Đối với tôi, việc giải thích khung dữ liệu giờ đây phụ thuộc vào hàng.Ví dụ,

  • Hàng 1- (n-1): có bao nhiêu tập tin được liên kết với một ngôn ngữ đặc biệt
  • Row n: có bao nhiêu tập tin được gắn liền với tất cả ngôn ngữ

Điều này trở nên khó hiểu hơn nếu bạn bắt đầu tập hợp dữ liệu của mình. Ví dụ: giả sử bạn muốn biết ngôn ngữ nào có nhiều hơn 100 Tệp:

> x = data.frame(Files=c(4009, 210, 35), 
       LOC=c(15328,876, 200), 
       row.names=c("C++", "Java", "Python"), 
       stringsAsFactors=FALSE)  
> x["Total" ,] = colSums(x) 
> x[x$Files > 100,] 
     Files LOC 
C++ 4009 15328 
Java 210 876 
Total 4254 16404#But this refers to all languages! 

Hàng Total hiện đã sai!

Cá nhân tôi sẽ tính toán tổng cột và lưu trữ chúng trong một véc tơ riêng biệt.

+1

Thông thường tôi sẽ không làm điều này để phân tích, nhưng đây là để trình bày. Đây là bước cuối cùng trước khi tôi tạo một bảng trong tài liệu LaTeX với Sweave. –

+1

@lorin Đủ công bằng – csgillespie

0

bản năng ban đầu của bạn sẽ làm việc nếu bạn ép buộc các cột của bạn để số:

y$LOC <- as.numeric(y$LOC) 
y$Files <- as.numeric(y$Files) 

Và sau đó áp dụng colSums() và rbind().

1

Vì bạn đề cập đến đây là bước cuối cùng trước khi xuất cho bản trình bày, bạn có thể có tên cột sẽ bao gồm khoảng trống trong chúng để rõ ràng (tức là "Tổng cộng"). Nếu vậy, sau đây sẽ bảo đảm rằng các data.frame tạo sẽ rbind để các tập dữ liệu ban đầu mà không có lỗi gây ra bởi tên cột không hạnh phúc:

dfTotals <- data.frame(Language="Total",t(colSums(x[,-1])))) 

colnames(dfTotals) <- names(x) 

rbind(x, dfTotals) 
6

Hãy thử điều này

y[4,] = c("Total", colSums(y[,2:3])) 
1

Tôi nghĩ rằng ngày nay có một cách dễ dàng hơn để điều này với các gói dplyr:

library(dplyr) 
x <- mutate(x, Total = rowSums(x[, 2:3])) 
0

Bạn có thể sử dụng áp dụng cho tất cả các khoản tiền col

Apply (df [-columns mà bạn không muốn trong tổng], 2, tổng hợp)

Và sau đó bạn có thể

rbind

dữ liệu đó trong bạn df

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