Заполнить NA набором предыдущих значений

У меня есть фрейм данных, который выглядит так:

d = data.frame(obs = 1:4, comp = c("7_10","5","6_9","1_2_6_9"))

  obs    comp
1   1    7_10
2   2       5
3   3     6_9
4   4 1_2_6_9

Столбец comp содержит информацию об элементах, которые можно найти в каждом наблюдении (строке). Итак, первое наблюдение содержит элементы 7 и 10, второе — элемент 5 и так далее. Каждое наблюдение может содержать один, два или четыре из возможных 10 элементов.

Я могу разделить их на отдельные столбцы:

library(tidyverse)
d %>% 
  separate_wider_delim(comp, 
                       delim = "_", 
                       names = c("e1", "e2", "e3", "e4"),
                       too_few = "align_start")

    obs e1    e2    e3    e4   
1     1 7     10    NA    NA   
2     2 5     NA    NA    NA   
3     3 6     9     NA    NA   
4     4 1     2     6     9  

Однако вместо NA мне нужно, чтобы информация повторялась, например:

    obs e1    e2    e3    e4   
1     1 7     10    7     10   # elements 7 and 10 repeat
2     2 5     5     5     5    # element 5 repeats
3     3 6     9     6     9   
4     4 1     2     6     9 

Я знаю, как использовать pivot_longer и fill, чтобы заполнить NA предыдущим значением:

d %>% 
  separate_wider_delim(comp, 
                       delim = "_", 
                       names = c("e1", "e2", "e3", "e4"),
                       too_few = "align_start") %>% 
  pivot_longer(2:5,
               names_to = "e",
               values_to = "code") %>% 
  fill(code, .direction = "down") %>% 
  pivot_wider(names_from = e,
              values_from = code)

    obs e1    e2    e3    e4   
1     1 7     10    10    10  
2     2 5     5     5     5    
3     3 6     9     9     9    
4     4 1     2     6     9   

Есть ли способ вместо этого заполнить NA набором предыдущих значений, а не только последним значением?

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

Angelos Amyntas 28.07.2024 18:15

Как вы хотите, чтобы замена работала, если у вас есть три значения?

IRTFM 28.07.2024 18:30

@IRTFM справедливый вопрос. У меня никогда не бывает трех ценностей. это 1,2 или 4 элемента. Я обновил основной текст

Angelos Amyntas 28.07.2024 18:55
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
85
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Если вы знаете, что последовательности комп состоят из 1, 2 или 4 элементов (если 1, то повторяется 4 раза, если 2, повторяется дважды, если 4 не повторяются), то вы можете использовать rep и указать целевую длину для каждого obs из 4. Добавлен знак row_number для отображения данных в широком формате, как показано в примере выше.

library(tidyverse)

d %>% 
  separate_longer_delim(comp, delim = "_") %>%
  reframe(value = rep_len(comp, length.out = 4), .by = obs) %>%
  mutate(name = row_number(), .by = obs) %>%
  pivot_wider(id_cols = obs, names_from = name, values_from = value, names_prefix = "e")

Выход

    obs e1    e2    e3    e4   
  <int> <chr> <chr> <chr> <chr>
1     1 7     10    7     10   
2     2 5     5     5     5    
3     3 6     9     6     9    
4     4 1     2     6     9

В основе мы могли бы начать с

> f = \(l) {
+   stopifnot(is.list(l))
+   nc = max(lengths(l))
+   do.call(rbind, lapply(l, rep, length.out=nc)) 
+ }
> d[-1L] = f(strsplit(d$comp, "_", fixed = TRUE))
> d 
  obs comp.1 comp.2 comp.3 comp.4
1   1      7     10      7     10
2   2      5      5      5      5
3   3      6      9      6      9
4   4      1      2      6      9

Примечание

Входные данные

d = data.frame(obs = 1:4, comp = c("7_10","5","6_9","1_2_6_9"))

С базой R вы можете попробовать read.table + `[<-`, как показано ниже.

cbind(
    d,
    t(
        apply(
            read.table(text = d$comp, sep = "_", fill = TRUE),
            1,
            \(x) `[<-`(x, na.omit(x))
        )
    )
)

такой, что вы получите

  obs    comp V1 V2 V3 V4
1   1    7_10  7 10  7 10
2   2       5  5  5  5  5
3   3     6_9  6  9  6  9
4   4 1_2_6_9  1  2  6  9

Вы можете воспользоваться правилом переработки data.frame:

f <- function(data) {
  newdata <- data.frame(t(data.frame(strsplit(data$comp, split = "_"))))
  data[names(newdata)] <- newdata
  data
}

f(d)

  obs    comp X1 X2 X3 X4
1   1    7_10  7 10  7 10
2   2       5  5  5  5  5
3   3     6_9  6  9  6  9
4   4 1_2_6_9  1  2  6  9

help(data.frame)

Объекты, передаваемые в data.frame, должны иметь одинаковое количество строк, но атомные векторы (см. is.vector), факторы и векторы символов защищено Я буду переработано целое число раз при необходимости (в том числе как элементы аргументов списка).

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