R - Возвращает имя столбца для строки, в которой найдено первое заданное значение

Я пытаюсь найти первое вхождение ЛОЖЬ в кадре данных для значения каждой строки. Мои строки - это конкретные случаи, а столбцы - даты. Я хотел бы найти дату первого FALSE, чтобы я мог использовать это значение для поиска даты возврата.

Пример структуры моего фрейма данных:

df <- data.frame(ID = c(1,2,3), '2001' = c(TRUE, TRUE, TRUE), 
                 '2002' = c(FALSE, TRUE, FALSE), '2003' = c(TRUE, FALSE, TRUE))

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

Например :

ID | Date
1  | 2002
2  | 2003
3  | 2002

Я не знаю, как получить такой результат.

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

Я новый пользователь R, поэтому, пожалуйста, не воздерживайтесь от предложений, о которых, возможно, уже думал более опытный пользователь R.

заранее спасибо


person JMade    schedule 17.11.2020    source источник


Ответы (2)


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

library(dplyr)
library(tidyr)
#Code
newdf <- df %>% pivot_longer(-ID) %>%
  group_by(ID) %>%
  filter(value==F) %>%
  filter(!duplicated(value)) %>% select(-value) %>%
  rename(Myname=name)

Выход:

# A tibble: 3 x 2
# Groups:   ID [3]
     ID Myname 
  <dbl> <chr>
1     1 2002 
2     2 2003 
3     3 2002 

Другой вариант без повторяющихся значений может использовать row_number() для извлечения первого значения (row_number()==1):

library(dplyr)
library(tidyr)
#Code 2
newdf <- df %>% pivot_longer(-ID) %>%
  group_by(ID) %>%
  filter(value==F) %>%
  mutate(V=ifelse(row_number()==1,1,0)) %>%
  filter(V==1) %>%
  select(-c(value,V)) %>% rename(Myname=name)

Выход:

# A tibble: 3 x 2
# Groups:   ID [3]
     ID Myname 
  <dbl> <chr>
1     1 2002 
2     2 2003 
3     3 2002 

Или используя base R с apply() и общую функцию:

#Code 3
out <- data.frame(df[,1,drop=F],Res=apply(df[,-1],1,function(x) names(x)[min(which(x==F))]))

Выход:

  ID  Res
1  1 2002
2  2 2003
3  3 2002
person Duck    schedule 17.11.2020
comment
Большое спасибо! Настоящая палочка-выручалочка. Как мне включить изменение имени результирующего столбца в новый фрейм данных? По умолчанию используется имя. (Я знаю, как изменить имя столбца постфактум, но мне любопытно, как бы вы включили его в предоставленный вами код. - person JMade; 18.11.2020
comment
@JMade Я обновил решение. Вы должны использовать rename() и присвоить желаемое имя. Надеюсь, это вам поможет! - person Duck; 18.11.2020
comment
Я опубликовал еще один вопрос, который является продолжением этого, о котором вы, вероятно, знаете: ссылка @Duck - person JMade; 18.11.2020

Мы можем использовать max.col с ties.method = 'first' после инвертирования логических значений.

cbind(df[1], Date = names(df[-1])[max.col(!df[-1], ties.method = 'first')])
#  ID Date
#1  1 2002
#2  2 2003
#3  3 2002
person Ronak Shah    schedule 18.11.2020