2013-01-11 2 views
0

Я немного потерял около лучший способ выполнить то, что я хочу в R.добавить столбцы, основанные на repetions и условий других столбцов R

У меня есть dataframe с несколькими столбцами. Одним из них является пользовательский и другой столбец, допустим, число (0,1,2,3,4,5). Иногда пользователь повторяется, но номер столбца должен иметь последовательность чисел в этом случае. Может быть что-то вроде этого:

user number column B column C 
1 0  85  200 
2 1  165  852 
1 2  200  1000 
3 0  15  689 
3 1  89  896 
4 0  78  582 
4 2  96  586 

То, что я хотел бы получить это:

user number status days 
1 0  0  200 
3 0  1  50 ->(value column C, user 3, number 1)-(value column B, user 3, number 0) 
4 0  0  200 

Я хочу, чтобы добавить две колонки в dataframe на основе значений из этих пользователей.

  • Если пользователь имеет номер == 0, но пользователь уникального статус == 0 и дни == некоторое предопределенное число
  • Если пользователь имеет номер == 0, и пользователь не является уникальным
    • Если второе появление пользователя имеет номер == 1, статус == 1 и дни должны быть вычитанием из столбца значений C второй вид столбца значения пользователя B первый вид пользователя
    • Если второе появление пользователя имеет number! = 1, status == 0 и days == некоторый предопределенный номер
  • Удалить из пользователей наборов данных, которые не имеют номер == 0

Я задаю этот вопрос, потому что я немного запутался о лучший способ сделать это. Я хотя о подмножестве dataframe, где number == 0, а затем сравнить пользователей между кадрами данных, чтобы увидеть повторных пользователей, но, возможно, это не лучший способ сделать это.

Любые указатели и идеи были бы замечательными!

Спасибо за вашу помощь

EDIT

columnB это количество дней, прошедших с '2002-01-01'. Например, первый пользователь вводит данные в течение 85 дней после 2002-01-01

columnC - количество дней, проведенных пользователем при наблюдении. После этих дней пользователь больше не находится в базе данных.

EDIT2

Мой набор данных имеет 36 столбцов и 26075rows

После некоторых предложений, где что у меня есть до сих пор.

#remove from dataset all users that don't have number == 0 
df1 <- df[df$user %in% df[df$number == 0,1],] 

df1["Status"] <- 0 

#doesn't work 
df1[df1$number == 1 %in% df1[duplicated(df1$user),]] 

То, что я пытался сделать это, чтобы найти все дублированные пользователей и, если число равно 1. Для того, чтобы попробовать что-то вроде этого впоследствии:

df1[df1$number == 1 %in% df1[duplicated(df1$user),]] <- df1$Status == 1 
+2

откуда 'days' пришел? .. «некоторое предопределенное число» не помогает нам помочь вам .. и ваши данные всегда сортируются по пользователю и номеру по возрастанию? :) –

+1

вы можете написать функцию, которая делает то, что вы хотите для одного пользователя, а затем использовать ddply для запуска этой функции для всех пользователей. – EDi

+0

Я не знаю других, но мне трудно понять из вашего примера и описания, что вы действительно хотите. Например, что такое столбец «C» или «B»? –

ответ

1
#order the dataset by columns needed 
df2 <- df2[order(df2$user, df2$number),] 

ids <- unique(df2$user) 

#create variable status and days 
status <- NULL 
end <- NULL 
for (i in 1:length(ids)) { 
    aux <- df2[df2$user %in% ids[i],] 
    if (nrow(aux) == 1 & aux$number[1] == 0){ 
      status[i] <- 0 
      days[i] <- end 
    } else if (nrow(aux) > 1) { 
      status[i] <- 1 
      days[i] <- aux$Event[2] 
    } else { 
      status[i] <- NA 
      days[i] <- NA 
    } 
} 

#merge the vector created with the database 
data <- data.frame(ids, status, days) 
df2 <- df2[!duplicated(df2$user),] 
df2 <- merge(df2, data, by.x="user", by.y="ids") 

#remove NAs from the dataset 
df.f <- df2[!(is.na(df2$days)),] 
1

Возможно subseting в data.frame за каждый пользователь не самый эффективный способ, но он может быть достаточно хорош для вашего объема данных, если вам не нужен ответ всего за несколько секунд.

ids = unique(df1$user); 
status.days = sapply(ids,function(id) { 
    udf = subset(df1,subset= user == id); 
    if (nrow(udf) == 1) { 
    status = 0; 
    days = XXX; # the predefined value. 
    } else if (udf$number[2] != 1) { 
    status = 0; 
    days = XXX; # the predefined value; 
    } else { 
    status = 1; 
    days = udf$columnC[2] - udf$columnB[1]; 
    } 
    c(status,days) 
}); 

status = sapply(status.days,simplify=T,function(sd) { sd[1] }); 
days = sapply(status.days,simplify=T,function(sd) { sd[2] }); 

result = data.frame(user=ids,number=rep(0,length(ids)),status=status,days=days) 

Я должен признаться, что я не уверен насчет индексации для извлечения статуса и дней из временного списка «status.days» ... возможно, вместо SD [1] и сд [2] он должен быть с.о. [1] [1], сд [1] [2] или сд [[1]] [1], сд [[1]] [2]

+0

Итак, чтобы сделать что-то вроде этого: df1 [df1 $ number == 1% in% df1 [duplicated (df1 $ user),]] (но работает: p) это невозможно? – pavid

+0

Если честно, я не знаю, какое это выражение произведет. Глядя на ваше последнее редактирование, я предполагаю, что вы хотите просто уникально (df1 $ user [df1 $ number == 1]) для определения идентификаторов этих пользователей. Или, может быть, вам нужно их количество == 1 записей? В этом случае df1 [df1 $ number == 1]. Разве не гарантировано, что если номер == 1 пользователь уже дублируется (у него больше, чем на строке с его идентификатором)? –

+0

В любом случае решение, которое я предоставляю, пытается решить начальную проблему сейчас, когда я думаю, что понимаю ее, не глядя на предыдущие обсуждения решений. Потенциальная проблема с этим решением заключается в том, что он может быть не самым эффективным, но я считаю, что он должен быть достаточно хорош для вашего объема данных. –

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