2017-01-17 13 views
7

Tôi có dữ liệu về nhiều dự án, trong đó mỗi dự án bao gồm một nhóm các cá nhân. Tôi có thông tin về thứ hạng và giới tính của họ, như vậy:Trả lại giá trị cao nhất trong vector và chuỗi trong cột có liên quan trong R

df <- read.table(header = TRUE, text = 'Project GenderA RankA GenderB RankB GenderC RankC 
      100 1 3 0 1 1 2 
      200 1 2 1 2 NA NA 
      300 0 3 1 3 0 2 
      400 0 1 NA NA NA NA 
      500 1 1 0 2 1 1') 

Đối với mỗi dự án, tôi muốn tạo biến mới với xếp hạng cao nhất trong nhóm và giới tính của người đó.

Project GenderA RankA GenderB RankB GenderC RankC HighGen HighRank 
    100  1  3  0  1  1  2  1  3 

tôi có thể có được thứ hạng cao nhất với Pmax:

df<-cbind(df, 
    HighRank = pmax(df$RankA, df$RankB, df$RankC)) 

Nhưng công trình này chỉ dành cho các dự án đã hoàn thành (có nghĩa là, không có NAS), và không liên quan đến cột giới. Cách tốt nhất để làm cả hai là gì?

+1

Bạn muốn xử lý các mối quan hệ như thế nào? – ulfelder

Trả lời

9

Đây là câu trả lời có ý kiến, nhưng lý do khiến việc này khó thực hiện một lần là dữ liệu của bạn không gọn gàng. Điều đó có nghĩa là trong trường hợp này bạn muốn mỗi hàng có một quan sát. Tôi cung cấp cho các đại diện 'gọn gàng' và một giải pháp sử dụng dplyr gói:

library(dplyr) 

df <- read.table(header = TRUE, text = 'Project Gender Rank order 
      100 1 3 A 
      100 0 1 B 
      100 1 2 C 
      200 1 2 A 
      200 1 2 B 
      200 NA NA C 
      300 0 3 A 
      300 1 3 B 
      300 0 2 C') 

df %>% group_by(Project) %>% arrange(-Rank) %>% slice(1) %>% ungroup() 

Để giải thích rằng dòng cuối cùng, bạn nhóm dự án, sắp xếp tất cả các điểm số trong những dự án do cấp bậc, sau đó lọc cho là người đầu tiên, và cuối cùng , đối với biện pháp tốt, bạn ungroup, có nghĩa là bạn 'quên' nhóm. Đầu ra của bạn sau đó là kỷ lục điểm cao nhất cho mỗi dự án, bao gồm cả điểm số, giới tính của nó. Lưu ý rằng tôi cũng đặt vào một biến mới 'trật tự', để phản ánh thực tế là dữ liệu được ghi dưới 'rankA' hoặc 'rankB' etcetera.

Out:

| Project| Gender| Rank|order | 
|-------:|------:|----:|:-----| 
|  100|  1| 3|A  | 
|  300|  0| 3|A  | 
|  200|  1| 2|A  | 

Tách dữ liệu vào đại diện gọn gàng có thể được thực hiện là tốt, nhưng bạn có thể muốn xem xét làm thế nào bạn đã nhập dữ liệu ở nơi đầu tiên. Đó là nó cho sự gọn gàng, nhưng đối với một đọc rộng rãi, bạn có thể xem http://vita.had.co.nz/papers/tidy-data.pdf.

Nhờ những nhận xét của Gregor, đây là một cách để chuyển đổi dataframe của bạn thành một đại diện gọn gàng hơn (bằng cách sử dụng gói tidyr)

library(tidyr) 


df <- read.table(header = TRUE, text = 'Project GenderA RankA GenderB RankB GenderC RankC 
      100 1 3 0 1 1 2 
      200 1 2 1 2 NA NA 
      300 0 3 1 3 0 2 
      400 0 1 NA NA NA NA 
      500 1 1 0 2 1 1') 

df %>% gather(key = key, value = value, -Project) %>% separate(key, into = c("variable", "order"), sep = -2) %>% spread(key = variable, value = value) 

Out:

| Project|order | Gender| Rank| 
|-------:|:-----|------:|----:| 
|  100|A  |  1| 3| 
|  100|B  |  0| 1| 
|  100|C  |  1| 2| 
|  200|A  |  1| 2| 
|  200|B  |  1| 2| 
|  200|C  |  NA| NA| 
|  300|A  |  0| 3| 
|  300|B  |  1| 3| 
|  300|C  |  0| 2| 
|  400|A  |  0| 1| 
|  400|B  |  NA| NA| 
|  400|C  |  NA| NA| 
|  500|A  |  1| 1| 
|  500|B  |  0| 2| 
|  500|C  |  1| 1| 

Sau đó bạn có thể ăn điều này cho công thức trong phần đầu tiên để có được giải pháp của bạn.

+5

Tôi đã chỉ làm việc trên một câu trả lời đó là cơ bản này. Mã để dọn dẹp dữ liệu bằng cách sử dụng 'dplyr' và' tidyr': 'op_df%>% thu thập (key = key, value = value, -Project)%>% riêng biệt (khóa, thành = c (" biến "," thứ tự "), sep = -2)%>% spread (khóa = biến, giá trị = giá trị) '. Vui lòng chỉnh sửa điều này vào câu hỏi của bạn. – Gregor

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