Сохранение одной строки и отбрасывание других в R с использованием определенных критериев?

#r #database

#r #База данных

Вопрос:

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

Так, например, для первых трех строк с идентификатором 13480 я хочу сохранить строку, содержащую 124, и отбросить две другие.

 id,sex,visits,sbp    
13480,M,2,124
13480,M,3,306
13480,M,4,116
13520,M,2,124
13520,M,3,116
13520,M,4,120
13580,M,2,NA
13580,M,3,124
 

Это самое дальнее, что я получил, пытался это настроить, но не уверен, что я на правильном пути:

 maxsbp <- split(sbp, sbp$sbp)
  r <- data.frame()
  for (i in 1:length(maxsbp)){
    one <- maxsbp[[i]]
    index <- which(one$sbp == max(one$sbp))
    select <- one[index,]
    r <- rbind(r, select) 
}
  r1 <- r[!(sbp$sbp>=300),]
  r1
 

Ответ №1:

Я думаю, что аккуратное решение для этого будет работать довольно хорошо. Я бы сначала отфильтровал все значения выше 300, если вы не хотите сохранять какое-либо значение выше этого порога. Затем group_by идентификатор, порядок и сохранение первого.

 my.df <- data.frame("id" = c(13480,13480,13480,13520,13520,13520,13580,13580),
                       "sex" = c("M","M","M","M","M","M","M","M"),
                       "sbp"= c(124,306,116,124,116,120,NA,124))
 
 my.df %>% filter(sbp < 300) # filter to retain only values below 300
      %>% group_by(id) # group by id
      %>% arrange(-sbp) # arrange by id in descending order
      %>% top_n(1, sbp) # retain first value i.e. the largest

# A tibble: 3 x 3
# Groups:   id [3]
#     id sex     sbp
#  <dbl> <chr> <dbl>
#1 13480 M       124
#2 13520 M       124
#3 13580 M       124
 

Ответ №2:

В R очень редко вам потребуются явные for циклы для выполнения задач.

Доступны функции, которые помогут вам выполнять такие групповые операции.

Например, в base R вы можете использовать subset и ave :

 subset(df,sbp == ave(sbp,id,FUN = function(x) max(sbp[sbp <= 300],na.rm = TRUE)))

#     id sex visits sbp
#1 13480   M      2 124
#4 13520   M      2 124
#8 13580   M      3 124
 

То же самое можно сделать, используя dplyr синтаксис которого немного легче понять.

 library(dplyr)
df %>%
  group_by(id) %>%
  filter(sbp == max(sbp[sbp <= 300], na.rm = TRUE))
 

Ответ №3:

slice_head также может быть использован

 my.df <- data.frame("id" = c(13480,13480,13480,13520,13520,13520,13580,13580),
                    "sex" = c("M","M","M","M","M","M","M","M"),
                    "sbp"= c(124,306,116,124,116,120,NA,124))

> my.df
     id sex sbp
1 13480   M 124
2 13480   M 306
3 13480   M 116
4 13520   M 124
5 13520   M 116
6 13520   M 120
7 13580   M  NA
8 13580   M 124
 

Действуйте просто так

 
my.df %>% group_by(id, sex) %>%
  arrange(desc(sbp)) %>%
  slice_head() %>%
  filter(sbp <300)

# A tibble: 2 x 3
# Groups:   id, sex [2]
     id sex     sbp
  <dbl> <chr> <dbl>
1 13520 M       124
2 13580 M       124