Я хочу повторить значения, пока новое значение не появится по группе. У меня есть функция, которую я нашел в Интернете некоторое время назад, которая почти делает то, что я ищу, но не совсем. Вот эта функция:

    repeat.before <- function(x) {
  ind <- which(!is.na(x))
  ind_rep <- ind
  if (is.na(x[1])) {
    ind_rep <- c(min(ind), ind)
    ind <- c(1, ind)
  }
  rep(x[ind_rep], times = diff(c(ind, length(x) + 1)))
}

Эта функция будет успешно повторять значение, пока не появится новое значение по группам. Проблема состоит в том, что если столбец начинается с NA, следующие строки, которые существуют до первого значения, в конечном итоге получат это первое значение вместо оставшегося NA. Я проиллюстрирую, что я имею в виду на этом примере:

    group    location 
    A        NA
    A        NA
    A        New York
    A        NA
    A        NA
    B        Chicago
    B        NA
    B        Philly
    B        NA

Код выше выведет это:

    group    location 
    A        New York
    A        New York
    A        New York
    A        New York
    A        New York
    B        Chicago
    B        Chicago
    B        Philly
    B        Philly

Что, опять же, очень близко к тому, что я ищу, но не совсем. Это вывод, который я ищу:

    group    location 
    A        NA
    A        NA
    A        New York
    A        New York
    A        New York
    B        Chicago
    B        Chicago
    B        Philly
    B        Philly

По сути, я не хочу, чтобы «повторяющийся» код начал работать, пока не найдет свое первое значение. Пока это не произойдет, я бы хотел, чтобы ряды оставались NA. Цель состоит в том, чтобы строки не классифицировались неправильно, то есть в приведенном выше примере первые две строки A не должны иметь метки New York.

4
Jared Annibale 1 Май 2019 в 18:43

3 ответа

Лучший ответ

Один из вариантов - fill после группировки по 'group'. Используйте fill с .direction, указанным как «вверх» или «вниз» (опция по умолчанию). Здесь нам нужен только вариант «вниз» на основе ожидаемого результата

library(dplyr)
library(tidyr)
df1 %>%
  group_by(group) %>%
  fill(location) 
# A tibble: 9 x 2
# Groups:   group [2]
#  group location
#  <chr> <chr>   
#1 A     <NA>
#2 A     <NA>
#3 A     New York
#4 A     New York
#5 A     New York
#6 B     Chicago 
#7 B     Chicago 
#8 B     Philly  
#9 B     Philly  

Данные

df1 <- structure(list(group = c("A", "A", "A", "A", "A", "B", "B", "B", 
 "B"), location = c(NA, NA, "New York", NA, NA, "Chicago", NA, 
 "Philly", NA)), class = "data.frame", row.names = c(NA, -9L))
5
akrun 1 Май 2019 в 15:50

Вы также можете использовать пакет zoo, используя функцию na.locf.

library(zoo)
df1 <-
  structure(list(
    group = c("A", "A", "A", "A", "A", "B", "B", "B",
              "B"),
    location = c(NA, NA, "New York", NA, NA, "Chicago", NA,
                 "Philly", NA)
  ),
  class = "data.frame",
  row.names = c(NA,-9L))

df1$location2 <- na.locf(df1$location, na.rm = F)
df1

  group location location2
1     A     <NA>      <NA>
2     A     <NA>      <NA>
3     A New York  New York
4     A     <NA>  New York
5     A     <NA>  New York
6     B  Chicago   Chicago
7     B     <NA>   Chicago
8     B   Philly    Philly
9     B     <NA>    Philly
2
CT Hall 1 Май 2019 в 15:57

База R

transform(df1,
          loc2 = ave(df1$location,
                     cumsum(!is.na(df1$location)),
                     FUN = function(x) x[1]))
#  group location     loc2
#1     A     <NA>     <NA>
#2     A     <NA>     <NA>
#3     A New York New York
#4     A     <NA> New York
#5     A     <NA> New York
#6     B  Chicago  Chicago
#7     B     <NA>  Chicago
#8     B   Philly   Philly
#9     B     <NA>   Philly
2
d.b 1 Май 2019 в 15:58