Заполнение отсутствующих уровней
У меня есть следующий тип фрейма данных:
Country <- rep(c("USA", "AUS", "GRC"),2)
Year <- 2001:2006
Level <- c("rich","middle","poor",rep(NA,3))
df <- data.frame(Country, Year,Level)
df
Country Year Level
1 USA 2001 rich
2 AUS 2002 middle
3 GRC 2003 poor
4 USA 2004 <NA>
5 AUS 2005 <NA>
6 GRC 2006 <NA>
Я хочу заполнить недостающие значения правильной меткой уровня в последнем из правого столбца.
Таким образом, ожидаемый результат должен быть таким:
Country Year Level
1 USA 2001 rich
2 AUS 2002 middle
3 GRC 2003 poor
4 USA 2004 rich
5 AUS 2005 middle
6 GRC 2006 poor
Ответы
Ответ 1
Мы можем группировать "Страна" и получать уникальное значение не-NA
library(dplyr)
df %>%
group_by(Country) %>%
dplyr::mutate(Level = Level[!is.na(Level)][1])
# A tibble: 6 x 3
# Groups: Country [3]
# Country Year Level
# <fctr> <int> <fctr>
#1 USA 2001 rich
#2 AUS 2002 middle
#3 GRC 2003 poor
#4 USA 2004 rich
#5 AUS 2005 middle
#6 GRC 2006 poor
Если мы загрузили dplyr
вместе с plyr
, лучше указать явно dplyr::mutate
или dplyr::summarise
так, чтобы он использовал функцию из dplyr
. В plyr
есть те же функции, что и потенциально может маскировать функции из dplyr
, когда они загружаются, создавая различное поведение.
Ответ 2
В базе R вы можете использовать ave()
:
transform(df, Level = ave(Level, Country, FUN = na.omit))
# Country Year Level
# 1 USA 2001 rich
# 2 AUS 2002 middle
# 3 GRC 2003 poor
# 4 USA 2004 rich
# 5 AUS 2005 middle
# 6 GRC 2006 poor
Другая, более точная возможность - использовать соединение. Здесь мы объединяем столбец Country
с данными, опущенными NA. Результат тот же, только в другом порядке строк.
merge(df["Country"], na.omit(df))
# Country Year Level
# 1 AUS 2002 middle
# 2 AUS 2002 middle
# 3 GRC 2003 poor
# 4 GRC 2003 poor
# 5 USA 2001 rich
# 6 USA 2001 rich
Ответ 3
Вы можете сделать это с помощью data.table
и zoo
: -
library(data.table)
library(zoo)
setDT(df)
df[, Level := na.locf(Level), by = Country]
Это даст вам: -
Country Year Level
1: USA 2001 rich
2: AUS 2002 middle
3: GRC 2003 poor
4: USA 2004 rich
5: AUS 2005 middle
6: GRC 2006 poor
Ответ 4
library(dplyr)
df %>%
group_by(Country) %>%
mutate(Level = replace(Level, is.na(Level), unique(na.omit(Level))))
Country Year Level
<fctr> <int> <fctr>
1 USA 2001 rich
2 AUS 2002 middle
3 GRC 2003 poor
4 USA 2004 rich
5 AUS 2005 middle
6 GRC 2006 poor
Или, более кратко, применяя идею @suchait к использованию na.locf
:
df %>%
group_by(Country) %>%
mutate(Level = zoo::na.locf(Level))
Ответ 5
Решение с использованием dplyr и tidyr.
library(dplyr)
library(tidyr)
df %>%
arrange(Country) %>%
fill(Level) %>%
arrange(Year)
# Country Year Level
# 1 USA 2001 rich
# 2 AUS 2002 middle
# 3 GRC 2003 poor
# 4 USA 2004 rich
# 5 AUS 2005 middle
# 6 GRC 2006 poor
Ответ 6
Вот еще одно решение data.table
, которое обновляет соединение, используя таблицу поиска, которая создается из данного набора данных:
library(data.table)
setDT(df)[df[!is.na(Level)], on = .(Country), Level := Level][]
Country Year Level
1: USA 2001 rich
2: AUS 2002 middle
3: GRC 2003 poor
4: USA 2004 rich
5: AUS 2005 middle
6: GRC 2006 poor