2015-03-13 2 views
2

Пример 2 (выдуманные), например, строки в ДФ:Как объединить строки в одном кадре данных в R (на основе повторяющихся значений под определенным столбцом)?

userid facultyid courseid schoolid 
167  265  NA  1678 
167  71111  301  NA 

Предположим, что у меня есть пара сотен дублированный идентификатор пользователя, как в приведенном выше примере. Однако подавляющее большинство пользователей имеют разные значения.

Как объединить строки с дублированным идентификатором пользователя таким образом, чтобы придерживаться значений столбцов в 1-й (из 2) строки, если первое значение не является NA (в этом случае NA будет заселено любым значением пришел со второго ряда)?

В сущности, исходя из приведенного выше примера, мой идеальный выход будет содержать:

userid facultyid courseid schoolid 
167  265  301  1678 

ответ

1
# initialize a vector that will contain row numbers which should be erased 
rows.to.erase <- c() 

# loop over the rows, starting from top 
for(i in 1:(nrow(dat)-1)) { 
    if(dat$userid[i] == dat$userid[i+1]) { 
    # loop over columns to recuperate data when a NA is present 
    for(j in 2:4) { 
     if(is.na(dat[i,j])) 
     dat[i,j] <- dat[i+1,j] 
    } 
    rows.to.erase <- append(rows.to.erase, i+1) 
    } 
} 

dat.clean <- dat[-rows.to.erase,] 
dat.clean 
# userid facultyid courseid schoolid 
# 1 167  265  301  1678 
1

Вот другой подход, использующий ddply:

# requires the plyr package 
library(plyr) 

# Your example dataframe with added lines 
schoolex <- data.frame(userid = c(167, 167, 200, 203, 203), facultyid = c(265, 71111, 200, 300, NA), 
         courseid = c(NA, 301, 302, 303, 303), schoolid = c(1678, NA, 1678, NA, 1678)) 

schoolex_duprm <- ddply(schoolex, .(userid), summarize, facultyid2 = facultyid[!is.na(facultyid)][1], 
           courseid2 = courseid[!is.na(courseid)][1], 
           schoolid2 = schoolid[!is.na(schoolid)][1]) 
+0

Привет, Харрисон, большое спасибо за ваш ответ! Есть ли более простой способ репликации вашей функции, если у меня есть почти 1000 столбцов/переменных, или мне придется выписать первый() аргумент для каждого из них? – poeticpersimmon

+0

@bergant предоставил решение для большого количества столбцов ... см. Ответ ниже –

1

Вот простой один вкладыш из plyr. Я написал немного больше, как правило, чем вы спросили:

a <- data.frame(x=c(1,2,3,1,2,3,1,2,3),y=c(2,3,1,1,2,3,2,3,1), 
     z=c(NA,1,NA,2,NA,3,4,NA,5),zz=c(1,NA,2,NA,3,NA,4,NA,5)) 

ddply(a,~x+y,summarize,z=first(z[!is.na(z)]),zz=first(zz[!is.na(zz)])) 

В частности, отвечая на первоначальный вопрос, если кадр данных назван,:

ddply(a,~userid,summarize,facultyid=first(facultyid[!is.na(facultyid)]), 
     courseid=first(courseid[!is.na(courseid)], 
     schoolid=first(schoolid[!is.na(schoolid)]) 
+0

Привет, Питер, большое спасибо за ваш ответ! Есть ли более простой способ репликации вашей функции, если у меня есть почти 1000 столбцов/переменных, или мне придется выписать первый() аргумент для каждого из них? – poeticpersimmon

4
aggregate(x = df1, by = list(df1$userid), FUN = function(x) na.omit(x)[1])[,-1] 

или использовать dplyr библиотеки:

library(dplyr) 

df1 %>% 
    group_by(userid) %>% 
    summarise_each(funs(first(na.omit(.)))) 
+0

Спасибо, @bergant! Не могли бы вы вкратце объяснить различные аргументы в вашей функции? – poeticpersimmon

+0

Переменная x в функции (FUN) представляет собой столбец (вектор) значений. Он вызывается для каждого столбца в data.frame и только для значений с одним и тем же идентификатором пользователя. Это сгруппированная операция - группа определяется аргументом 'by'. – bergant

Смежные вопросы