Извлечение строк с дубликатами записей в одном столбце, удовлетворяющих заданному условию в другом столбце - PullRequest
2 голосов
/ 17 февраля 2020

У меня есть образец кадра данных с повторяющимися записями в первом столбце, указанном ниже:

df <- data.frame(ID=c(rep(101,3),rep(102,2),103,rep(104,3)),Type=c(2,1,1,1,2,1,3,1,2),sex=c(0,0,0,1,1,1,0,0,0))
df
  ID Type sex
1 101    2   0
2 101    1   0
3 101    1   0
4 102    1   1
5 102    2   1
6 103    1   1
7 104    3   0
8 104    1   0
9 104    2   0

Вопрос: Для каждой переменной 'ID' я хочу, чтобы строки начинались с того места, где первое вхождение переменной 'Type' равно 1 (то есть Type = 1).

Я знаю, для каждого идентификатора, позиция, удовлетворяющая условию Тип = 1 , используя следующий код:

aggregate(df$Type,list(ID=df$ID),function(x) match(1,x))
 ID x
1 101 2
2 102 1
3 103 1
4 104 2

, но я не смог решить проблему ,

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

df.result <- data.frame(ID=c(101,101,102,102,103,104,104),Type=c(1,1,1,2,1,1,2),sex=c(0,0,1,1,1,0,0))
df.result
 ID Type sex
1 101    1   0
2 101    1   0
3 102    1   1
4 102    2   1
5 103    1   1
6 104    1   0
7 104    2   0

Спасибо!

Ответы [ 4 ]

2 голосов
/ 17 февраля 2020

Вот базовое решение R, использующее

dfout <- do.call(rbind,
                 c(make.row.names = F,
                   Map(function(v) v[head(which(v$Type==1),1):nrow(v),],split(df,df$ID))))

, такое что

> dfout
   ID Type sex
1 101    1   0
2 101    1   0
3 102    1   1
4 102    2   1
5 103    1   1
6 104    1   0
7 104    2   0
1 голос
/ 17 февраля 2020

Мы можем использовать match с slice

library(dplyr)
df %>% group_by(ID) %>% slice(match(1, Type) : n())

#    ID  Type   sex
#  <dbl> <dbl> <dbl>
#1   101     1     0
#2   101     1     0
#3   102     1     1
#4   102     2     1
#5   103     1     1
#6   104     1     0
#7   104     2     0

Или используя filter

df %>% group_by(ID) %>% filter(row_number() >= match(1, Type))

В базе R мы можем использовать ave как :

subset(df, as.logical(ave(Type, ID, FUN = function(x) seq_along(x) >= match(1, x))))
1 голос
/ 17 февраля 2020

Другой вариант использует cumsum():

library(dplyr)
df %>% 
  group_by(ID) %>% 
  filter(cumsum(Type==1) > 0)
1 голос
/ 17 февраля 2020

Вы можете использовать slice, то есть

library(dplyr)

df %>% 
 group_by(ID) %>% 
 slice(which(Type == 1)[1]:n())

, что дает,

# A tibble: 7 x 3
# Groups:   ID [4]
     ID  Type   sex
  <dbl> <dbl> <dbl>
1   101     1     0
2   101     1     0
3   102     1     1
4   102     2     1
5   103     1     1
6   104     1     0
7   104     2     0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...