Поиск нескольких строк в кадре данных, снизу вверх, если условно?

У меня есть датафрейм с несколькими столбцами, давайте назовем его dat1, и мне нужно извлечь строки в определенных столбцах на основе множества условий. Существует около 350 строк для каждого субъекта, и мне нужно найти последнюю строку определенной строки в определенном столбце, для каждого субъекта, содержащую определенное имя, например, "зеленый", и взять значение из другой строки в той же строке.

subject   type    value
111       yellow   354
111       green    584
111       yellow   584
111       blue     492
111       green    493
222       blue     459
222       green    583
222       yellow   539
222       blue     392
222       yellow   394

Скажем, мне нужно последнее значение "зеленый" для каждого предмета, как я могу это сделать?

После этого мне также нужно получить значение, которое выше последнего "зеленого", желательно сохранить его в двух отдельных векторах.

last_green    before_last_green
   493          492
   583          459

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

Можно ли искать первый "зеленый" снизу каждого предмета? Или как еще это можно сделать?

4 ответа

Решение

Отвечая на оба вопроса:

df=data.frame("subject"=c(rep(111,5),rep(222,5)),
           "type"=c("yellow","green","yellow","blue","green",
                    "blue","green","yellow","blue","yellow"),
           value=c(354,584,584,492,493,459,583,539,392,394),
           stringsAsFactors = FALSE)
   subject   type value
1      111 yellow   354
2      111  green   584
3      111 yellow   584
4      111   blue   492
5      111  green   493
6      222   blue   459
7      222  green   583
8      222 yellow   539
9      222   blue   392
10     222 yellow   394

Создать фильтр df:

filter_=df%>%rownames_to_column()%>%group_by(subject)%>%
  filter(type=="green")%>%slice(n())

last_green=filter_$value
before_last_green=df$value[as.numeric(filter_$rowname)-1]

Результаты:

> last_green
[1] 493 583
> before_last_green
[1] 492 459

Объяснение:
Сначала мы создаем имена строк, чтобы отслеживать положение последних green внешний вид для каждого subject, Затем мы группируем по subject и фильтровать по type мы берем последний элемент на группу с slice(), Затем мы возвращаем value в last_green и value строки с положением этих предыдущих образцов - 1 (предыдущий).

@thothal @boski @utubun Итак, я опробовал все ваши решения, которые отлично работают на примере данных, которые я привел здесь. Тем не менее, при адаптации его к моим фактическим данным я получаю ошибку

Error in filter_impl(.data, quo) : 

Ошибка оценки: объект "тип" не найден.

Из этого я получаю, что тип столбцов, которые я использую, имеет неправильный тип. Я определил их столбцы как символы, которые не помогли. У меня такое чувство, что есть кое-что, чего мне не хватает, чтобы заставить его работать, какая-нибудь подсказка, что?

Код

tidyverse твой друг:

library(tidyverse)
d <- structure(list(subject   = c(111L, 111L, 111L, 111L, 111L, 
                                  222L, 222L, 222L, 222L, 222L), 
                    type      = c("yellow", "green", "yellow", "blue", "green",
                                  "blue", "green", "yellow", "blue", "yellow"), 
                    value     = c(354L, 584L, 584L, 492L, 493L, 
                                  459L, 583L, 539L, 392L, 394L)), 
                    row.names = c(NA, -10L), 
                    class = c("tbl_df", "tbl", "data.frame"))

d %>% 
  group_by(subject) %>% 
  filter(type == "green") %>% 
  summarise_all(last)

# A tibble: 2 x 3
#   subject type  value
#     <int> <chr> <int>
# 1     111 green   493
# 2     222 green   583

объяснение

  • с group_by Вы будете делать следующее за уникальное значение subject
  • с filter вы смотрите только на строки с type равно green
  • с summarise вы наконец выбираете только последнюю запись

Вы можете сделать это следующим образом:

library(tidyverse)

dat %>%
  rownames_to_column() %>%
  group_by(subject) %>%
  filter(type == 'green') %>%
  summarise(
    last_green        = last(value), 
    before_last_green = dat$value[as.numeric(last(rowname)) - 1]
    )

Что здесь происходит:

  • вы перемещаете имена строк вашего data.frame в переменную rowname (см. последнее почему);
  • вы группируете свои данные по subject, чтобы применить следующие операции над подмножествами ваших данных, связанных с конкретным subject;
  • вы filter ваши данные, оставляя только greens;
  • и наконец:
    • вы summarize ваши данные, принимая последние value для каждого ранее отфильтрованного подмножества и присвоения его value_green;
    • Вы заимствуете целое, не преобразованное dat из среды, подмножество value от dat по строкам, соответствующим last(ronwame) - 1 вашей . данные, т.е. данные, которые пришли в summarize через трубы.

Который оценивает:

# A tibble: 2 x 3
  subject last_green before_last_green
    <int>      <int>             <int>
1     111        493               492
2     222        583               459

Ваши данные:

dat <- read.table(
  text = "subject   type    value
111       yellow   354
111       green    584
111       yellow   584
111       blue     492
111       green    493
222       blue     459
222       green    583
222       yellow   539
222       blue     392
222       yellow   394",
  header = T, stringsAsFactors = F
)
Другие вопросы по тегам