2015-05-21 19 views
6

Tôi khá mới đối với R và đây là lần đầu tiên tôi dám đặt câu hỏi tại đây.R tổng các hàng cho các nhóm cột khác nhau bắt đầu bằng chuỗi tương tự

Tôi đang làm việc với tập dữ liệu có thang tỷ lệ và tôi muốn xếp hàng trên các nhóm cột khác nhau chia sẻ các chuỗi đầu tiên trong tên của chúng.

Dưới đây tôi xây dựng một khung dữ liệu chỉ có 2 hàng để minh họa cách tiếp cận mà tôi đã theo dõi, mặc dù tôi muốn nhận được phản hồi về cách tôi có thể viết một cách hiệu quả hơn để thực hiện nó.

df <- as.data.frame(rbind(rep(sample(1:5),4),rep(sample(1:5),4))) 

var.names <- c("emp_1","emp_2","emp_3","emp_4","sat_1","sat_2" 
      ,"sat_3","res_1","res_2","res_3","res_4","com_1", 
      "com_2","com_3","com_4","com_5","cap_1","cap_2", 
      "cap_3","cap_4") 

names(df) <- var.names 

Vì vậy, những gì tôi đã làm, là để sử dụng chức năng grep để có thể tổng hợp các hàng của các biến đã xác định rằng bắt đầu với chuỗi nhất định và lưu trữ chúng trong một biến mới. Nhưng tôi phải viết một dòng mã mới cho mỗi biến.

df$emp_t <- rowSums(df[, grep("\\bemp.", names(df))]) 
df$sat_t <- rowSums(df[, grep("\\bsat.", names(df))]) 
df$res_t <- rowSums(df[, grep("\\bres.", names(df))]) 
df$com_t <- rowSums(df[, grep("\\bcom.", names(df))]) 
df$cap_t <- rowSums(df[, grep("\\bcap.", names(df))]) 

Nhưng có nhiều biến hơn trong tập dữ liệu và tôi muốn biết liệu có cách nào để thực hiện điều này chỉ với một dòng mã hay không. Ví dụ, một số cách để nhóm các biến bắt đầu bằng các chuỗi giống nhau và sau đó áp dụng hàm hàng.

Cảm ơn trước!

+0

Vâng, nếu đó là thao tác bạn cần thực hiện thường xuyên, có vẻ như dữ liệu của bạn có hình dạng sai. Sẽ dễ dàng hơn khi làm việc với dữ liệu ở định dạng "dài" thay vì định dạng "rộng" mà bạn hiện có. Có rất nhiều câu hỏi khác trên đó về định hình lại nếu đó là điều bạn muốn làm. – MrFlick

Trả lời

3

Một giải pháp khả thi là để transpose df và tính toán số tiền cho các cột đúng bằng cơ sở R rowsum chức năng (sử dụng set.seed(123))

cbind(df, t(rowsum(t(df), sub("_.*", "_t", names(df))))) 
# emp_1 emp_2 emp_3 emp_4 sat_1 sat_2 sat_3 res_1 res_2 res_3 res_4 com_1 com_2 com_3 com_4 com_5 cap_1 cap_2 cap_3 cap_4 cap_t 
# 1  2  4  5  3  1  2  4  5  3  1  2  4  5  3  1  2  4  5  3  1 13 
# 2  1  3  4  2  5  1  3  4  2  5  1  3  4  2  5  1  3  4  2  5 14 
# com_t emp_t res_t sat_t 
# 1 15 14 11  7 
# 2 15 10 12  9 
+0

ooohh, rất gần ... Tôi nghĩ tôi thích bạn hơn (+1) – BrodieG

+0

@BrodieG không biết, tôi đang sử dụng 't' hai lần ở đây, vì vậy không chắc nó sẽ mở rộng như thế nào. (+1) cho bạn quá :). Ý tưởng hay thay thế bằng '_t' thay vì chỉ' '" 'btw. –

+0

Cảm ơn mọi người vì đã trả lời. Cho đến bây giờ tôi không biết biểu thức thông thường là gì, nhưng vì tôi không hiểu tại sao phần "_. * $" Lại hoạt động tôi phải đọc và phát hiện ra rằng $ không cần thiết ở đây, 'cbind (df, t (rowsum (t (df), phụ ("_.* "," _t ", tên (df)))))' chỉ hoạt động tốt – csmontt

2

Đồng ý với MrFlick mà bạn có thể muốn đưa dữ liệu của bạn ở định dạng dài (xem reshape2, tidyr), nhưng để trả lời câu hỏi của bạn:

cbind(
    df, 
    sapply(split.default(df, sub("_.*$", "_t", names(df))), rowSums) 
) 

sẽ làm các trick

1

Bạn sẽ tốt hơn trong thời gian dài nếu bạn đặt dữ liệu của mình vào tidy format. Vấn đề là dữ liệu ở dạng rộng hơn là một định dạng dài. Và tên biến, ví dụ: emp_1, thực ra là hai phần dữ liệu riêng biệt: lớp của người đó và số ID của người đó (hoặc thứ gì đó tương tự). Đây là một giải pháp cho vấn đề của bạn với dplyr và tidyr.

library(dplyr) 
library(tidyr) 
df %>% 
    gather(key, value) %>% 
    extract(key, c("class", "id"), "([[:alnum:]]+)_([[:alnum:]]+)") %>% 
    group_by(class) %>% 
    summarize(class_sum = sum(value)) 

Trước tiên, chúng tôi chuyển đổi khung dữ liệu từ định dạng rộng sang dài với gather(). Sau đó, chúng tôi chia các giá trị emp_1 thành các cột riêng biệt classid với extract(). Cuối cùng, chúng tôi nhóm theo lớp và tổng hợp các giá trị trong mỗi lớp. Kết quả:

Source: local data frame [5 x 2] 

    class class_sum 
1 cap  26 
2 com  30 
3 emp  23 
4 res  22 
5 sat  19 
+0

Bạn có nghĩa vụ lấy hai giá trị cho mỗi lớp ở đây. –

+0

Tôi thấy câu hỏi ban đầu có hai câu trả lời (ví dụ) một câu trả lời cho mỗi hàng.Nhưng có vẻ như điểm đó là tổng hợp chúng? Nếu không, thì có một biến ẩn ở đây. Trong df ban đầu, cần phải có một cột khác xác định những gì xác định mỗi hàng, cột đó sẽ được bao gồm trong lời gọi đến 'group_by()'. Việc hợp nhất dữ liệu gốc trở nên dễ dàng hơn. nơi 'tóm tắt' để thêm một cột mới với dữ liệu đó, hoặc có thể' left_join() 'khung dữ liệu mới này quay trở lại khung dữ liệu đã được dọn dẹp. –

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