Создать новый столбец на основе наличия/отсутствия строки в другом столбце по группе

У меня есть этот набор данных о местонахождении судов, где один и тот же «id» может соответствовать двум уровням. Соответствует определенной категории, например «рыбалка», а также может отображаться как «неопределенная». Я хотел бы создать новый столбец, где всякий раз, когда «id» отображается как «неопределенное», а также как другая категория (в других строках), «неопределенное» заменяется этой категорией.

#dataset example
library(dplyr)

levels <- c("passenger", "passenger", "unspecified", "passenger", "passenger",
            "passenger", "passenger", "passenger", "passenger", "passenger",
            "unspecified", "passenger", "fishing", "unspecified", "fishing", 
            "fishing", "fishing","unspecified", "fishing", "fishing", 
            "unspecified","fishing", "fishing", "fishing", "unspecified",
            "unspecified", "unspecified")
id <- c("844", "844", "844", "844", "844","844", "844", "844", "844", "844",
        "844", "844", "845", "845", "845", "845", "845","845", "845", "845", 
        "845","845", "845", "845", "825", "825", "825")
lat <- c(-30.6456, -29.5648, -27.6667, -31.5587, -30.6934, -29.3147, -23.0538, 
         -26.5877, -26.6923, -23.40865, -23.1143, -23.28331, -31.6456, -24.5648, 
         -27.6867, -31.4587, -30.6784, -28.3447, -23.0466, -27.5877, -26.8524, 
         -23.8855, -24.1143, -23.5874, -23.5259, -22.8788, -22.1324)
long <- c(-50.4879, -49.8715, -51.8716, -50.4456, -50.9842, -51.9787, -41.2343, 
          -40.2859, -40.19599, -41.64302, -41.58042, -41.55057, -50.4576, -48.8715, 
          -51.4566, -51.4456, -50.4477, -50.9937, -41.4789, -41.3859, -40.2536, 
          -41.6502, -40.5442, -41.4057, -40.4058, -42.4877, -41.4545)

df <- tibble(levels = as.factor(levels), id  = as.factor(id), lat, long)

Вот мой ожидаемый результат:

> output %>% print(n = 27)
# A tibble: 27 x 5
   levels      id      lat  long new_colum  
   <fct>       <fct> <dbl> <dbl> <fct>      
 1 passenger   844   -30.6 -50.5 passenger  
 2 passenger   844   -29.6 -49.9 passenger  
 3 unspecified 844   -27.7 -51.9 passenger  
 4 passenger   844   -31.6 -50.4 passenger  
 5 passenger   844   -30.7 -51.0 passenger  
 6 passenger   844   -29.3 -52.0 passenger  
 7 passenger   844   -23.1 -41.2 passenger  
 8 passenger   844   -26.6 -40.3 passenger  
 9 passenger   844   -26.7 -40.2 passenger  
10 passenger   844   -23.4 -41.6 passenger  
11 unspecified 844   -23.1 -41.6 passenger  
12 passenger   844   -23.3 -41.6 passenger  
13 fishing     845   -31.6 -50.5 fishing    
14 unspecified 845   -24.6 -48.9 fishing    
15 fishing     845   -27.7 -51.5 fishing    
16 fishing     845   -31.5 -51.4 fishing    
17 fishing     845   -30.7 -50.4 fishing    
18 unspecified 845   -28.3 -51.0 fishing    
19 fishing     845   -23.0 -41.5 fishing    
20 fishing     845   -27.6 -41.4 fishing    
21 unspecified 845   -26.9 -40.3 fishing    
22 fishing     845   -23.9 -41.7 fishing    
23 fishing     845   -24.1 -40.5 fishing    
24 fishing     845   -23.6 -41.4 fishing    
25 unspecified 825   -23.5 -40.4 unspecified
26 unspecified 825   -22.9 -42.5 unspecified
27 unspecified 825   -22.1 -41.5 unspecified

Это для тех случаев, когда одно и то же id есть unspecified, но оно принадлежит какому-то другому уровню. Когда просто unspecified так и остается, когда тоже относится к другому уровню заменяет unspecified на этот.

Можешь объяснить логику new_column? Когда это становится passenger или fishing или unspecified?

user438383 06.05.2022 15:57

Да. Это для случаев, когда «ID» «не указан», но это также какая-то другая категория. Когда это просто «неопределенно», оно остается таким, когда оно «находит» свою другую категорию, заменяет ею «неопределенное». улучшенный?

Caroline Portal 06.05.2022 16:01

Теперь, когда я понял, я не включил последние строки с идентификатором, который остается «неуказанным». Извините за ошибку.

Caroline Portal 06.05.2022 16:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
40
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я считаю, что это самое простое/наиболее интуитивное решение:

Оператор case_when проверяет каждую группу — если все levels являются "unspecified", то new_column становится "unspecified", в противном случае, если он содержит либо "fishing", либо "passenger", он становится одним из них.

library(dplyr)
df %>%
    group_by(id) %>%
    mutate(new_column = case_when(
        all(levels == "unspecified") ~ "unspecified",
        any(levels == "fishing") ~ "fishing",
        any(levels == "passenger") ~ "passenger"
        )
    )
# A tibble: 27 × 5
# Groups:   id [3]
   levels      id      lat  long new_column 
   <fct>       <fct> <dbl> <dbl> <chr>      
 1 passenger   844   -30.6 -50.5 passenger  
 2 passenger   844   -29.6 -49.9 passenger  
 3 unspecified 844   -27.7 -51.9 passenger  
 4 passenger   844   -31.6 -50.4 passenger  
 5 passenger   844   -30.7 -51.0 passenger  
 6 passenger   844   -29.3 -52.0 passenger  
 7 passenger   844   -23.1 -41.2 passenger  
 8 passenger   844   -26.6 -40.3 passenger  
 9 passenger   844   -26.7 -40.2 passenger  
10 passenger   844   -23.4 -41.6 passenger  
11 unspecified 844   -23.1 -41.6 passenger  
12 passenger   844   -23.3 -41.6 passenger  
13 fishing     845   -31.6 -50.5 fishing    
14 unspecified 845   -24.6 -48.9 fishing    
15 fishing     845   -27.7 -51.5 fishing    
16 fishing     845   -31.5 -51.4 fishing    
17 fishing     845   -30.7 -50.4 fishing    
18 unspecified 845   -28.3 -51.0 fishing    
19 fishing     845   -23.0 -41.5 fishing    
20 fishing     845   -27.6 -41.4 fishing    
21 unspecified 845   -26.9 -40.3 fishing    
22 fishing     845   -23.9 -41.7 fishing    
23 fishing     845   -24.1 -40.5 fishing    
24 fishing     845   -23.6 -41.4 fishing    
25 unspecified 825   -23.5 -40.4 unspecified
26 unspecified 825   -22.9 -42.5 unspecified
27 unspecified 825   -22.1 -41.5 unspecified

Вы можете использовать оператор ifelse, чтобы указать условие, при котором существует только один тип levelsИ, в то время как levels равно «не указано», не изменяйте эти записи. В противном случае измените его на другой levels, который не является «неуказанным».

library(dplyr)

df %>% 
  group_by(id) %>% 
  mutate(new_column = ifelse(n_distinct(levels) == 1 & levels == "unspecified",
                             as.character(levels), 
                             as.character(levels)[levels != "unspecified"]))

# A tibble: 27 × 5
# Groups:   id [3]
   levels      id      lat  long new_column 
   <fct>       <fct> <dbl> <dbl> <chr>      
 1 passenger   844   -30.6 -50.5 passenger  
 2 passenger   844   -29.6 -49.9 passenger  
 3 unspecified 844   -27.7 -51.9 passenger  
 4 passenger   844   -31.6 -50.4 passenger  
 5 passenger   844   -30.7 -51.0 passenger  
 6 passenger   844   -29.3 -52.0 passenger  
 7 passenger   844   -23.1 -41.2 passenger  
 8 passenger   844   -26.6 -40.3 passenger  
 9 passenger   844   -26.7 -40.2 passenger  
10 passenger   844   -23.4 -41.6 passenger  
11 unspecified 844   -23.1 -41.6 passenger  
12 passenger   844   -23.3 -41.6 passenger  
13 fishing     845   -31.6 -50.5 fishing    
14 unspecified 845   -24.6 -48.9 fishing    
15 fishing     845   -27.7 -51.5 fishing    
16 fishing     845   -31.5 -51.4 fishing    
17 fishing     845   -30.7 -50.4 fishing    
18 unspecified 845   -28.3 -51.0 fishing    
19 fishing     845   -23.0 -41.5 fishing    
20 fishing     845   -27.6 -41.4 fishing    
21 unspecified 845   -26.9 -40.3 fishing    
22 fishing     845   -23.9 -41.7 fishing    
23 fishing     845   -24.1 -40.5 fishing    
24 fishing     845   -23.6 -41.4 fishing    
25 unspecified 825   -23.5 -40.4 unspecified
26 unspecified 825   -22.9 -42.5 unspecified
27 unspecified 825   -22.1 -41.5 unspecified 
Ответ принят как подходящий

Вы можете заменить "unspecified" на NA, заполнить эти NA предыдущим значением в той же группе id, а затем заменить оставшиеся NA обратно на "unspecified".

library(tidyverse)

df %>%
  mutate(new_colum = na_if (levels, "unspecified")) %>%
  group_by(id) %>% 
  fill(new_colum) %>%
  ungroup() %>%
  replace_na(list(new_colum = "unspecified"))
# A tibble: 27 × 5
   levels      id      lat  long new_colum  
   <fct>       <fct> <dbl> <dbl> <fct>      
 1 passenger   844   -30.6 -50.5 passenger  
 2 passenger   844   -29.6 -49.9 passenger  
 3 unspecified 844   -27.7 -51.9 passenger  
 4 passenger   844   -31.6 -50.4 passenger  
 5 passenger   844   -30.7 -51.0 passenger  
 6 passenger   844   -29.3 -52.0 passenger  
 7 passenger   844   -23.1 -41.2 passenger  
 8 passenger   844   -26.6 -40.3 passenger  
 9 passenger   844   -26.7 -40.2 passenger  
10 passenger   844   -23.4 -41.6 passenger  
11 unspecified 844   -23.1 -41.6 passenger  
12 passenger   844   -23.3 -41.6 passenger  
13 fishing     845   -31.6 -50.5 fishing    
14 unspecified 845   -24.6 -48.9 fishing    
15 fishing     845   -27.7 -51.5 fishing    
16 fishing     845   -31.5 -51.4 fishing    
17 fishing     845   -30.7 -50.4 fishing    
18 unspecified 845   -28.3 -51.0 fishing    
19 fishing     845   -23.0 -41.5 fishing    
20 fishing     845   -27.6 -41.4 fishing    
21 unspecified 845   -26.9 -40.3 fishing    
22 fishing     845   -23.9 -41.7 fishing    
23 fishing     845   -24.1 -40.5 fishing    
24 fishing     845   -23.6 -41.4 fishing    
25 unspecified 825   -23.5 -40.4 unspecified
26 unspecified 825   -22.9 -42.5 unspecified
27 unspecified 825   -22.1 -41.5 unspecified

Другие вопросы по теме