R:从一个列中排序/选择与同一数据帧中不同列的特定值相对应的值的有效方法

时间:2015-02-28 17:57:32

标签: r dataframe

我正在处理一个名为Student_Majr2的数据框,其中有大约60K行和两个相关列:一个用于匿名学生ID号,另一个用于学生宣布其专业的日期/期限(下面的前两个)。问题是大量学生改变了他们的专业,因此对于每个学生ID,可能有不止一个相关的日期。大约有30,000个唯一学生ID。我的目标是创建一个新的数据框,该数据框只包含每个学生ID的最新主要声明日期(即他们最终的主要选择)。以下是数据框的结构:

'data.frame':   59749 obs. of  5 variables:
 $ studentID               : int  1 2 2 2 4 4 5 6 8 8 ...
 $ SGBSTDN_TERM_CODE_EFF   : int  199920 199920 200040 200320 200130 200220 200140 200020 200430 200540 ...
 $ SGBSTDN_MAJR_CODE_1     : chr  "720" "966" "996" "906" ...
 $ SGBSTDN_MAJR_CODE_CONC_1: chr  "" "" "" "" ...
 $ SGBSTDN_LEVL_CODE       : chr  "UG" "UG" "UG" "UG" ...

我已创建以下脚本来实现此目标,并且它是有效的。但是,使用R-Studio和R版本3.1.1,运行Windows 8.1的corei5处理器的PC上也运行效率非常低。 (我实际上不知道花了多长时间,我在几个小时后上床睡觉,并在七个小时后的早上完成了。)

我确信有一种更有效的方法来执行此操作,因此我不必在睡觉时继续运行这样的脚本,但我无法弄清楚它是什么。我非常感谢任何建议和帮助。

library(dplyr)
final_majr <- data.frame() # the final dataframe with final major per student ID
tbl_df(final_majr)
students <- unique(Student_Majr2$studentID) #students gets vector with all unique student ids
for (i in students) { #loop through all student id numbers
        temp_majr <- data.frame() #set up temporary dataframe for each unique student id and major
        tbl_df(temp_majr)

                for (q in 1:nrow(Student_Majr2)) { #loop through all row numbers from student_major df
                        if (Student_Majr2$studentID[q] == i){ #identify rows for each student ID from top loop 
                                temp_majr <- rbind(temp_majr, Student_Majr2[q, ]) #and add to temp_majr df
                        }
                }
        temp_majr <- arrange(temp_majr, SGBSTDN_TERM_CODE_EFF) #order the rows using dplyr package
        m <- nrow(temp_majr) # m gets the total number of rows in temp_majr
        final_majr <- rbind(final_majr, temp_majr[m, ]) #and here we add the bottom row to final_majr
}

非常感谢您对此脚本的任何帮助。我经常咨询stackoverflow以获得编程方面的帮助,这是我的第一个问题/帖子。感谢您提供有关如何使我的问题更易于理解和回答的任何反馈。

2 个答案:

答案 0 :(得分:1)

基础R 解决方案。您可以order数据,然后使用duplicated选择所需的行。

# some data
dat <- data.frame(studentID = c(1, 2, 2, 2, 4, 4, 5, 6, 8, 8),
                  SGBSTDN_TERM_CODE_EFF = c(199920, 199920, 200040, 200320, 200130, 200220, 200140, 200020, 200430, 200540),
                  SGBSTDN_MAJR_CODE_1 = letters[1:10])

# order data by id and latest date first
dat <- with(dat, dat[order(studentID, -SGBSTDN_TERM_CODE_EFF), ])

# select first observation
with(dat, dat[!duplicated(studentID), ])
# studentID SGBSTDN_TERM_CODE_EFF SGBSTDN_MAJR_CODE_1
# 1          1                199920                   a
# 4          2                200320                   d
# 6          4                200220                   f
# 7          5                200140                   g
# 8          6                200020                   h
# 10         8                200540                   j

答案 1 :(得分:1)

如果您想为每个studentID选择一个SGBSTDN_TERM_CODE_EFF行,那么您可以使用dplyr执行library(dplyr) df %>% group_by(studentID) %>% arrange(SGBSTDN_TERM_CODE_EFF) %>%slice(n()) 行:

{{1}}