#r
Вопрос:
Для простоты предположим, что у меня есть две колонки. Первый: идентификатор (строка кодов, таких как AA23, BA53, NA и т.д.) Второе: Возраст (18, 32, 55, 23 и т.д.)
И идентификаторы иногда повторяются (т. е. один человек — AA23 заполнял опрос за два дня, но только в первый день его спросили, сколько ему лет, а во второй и третий день нет).
Я хочу скопировать значения вставки из столбца Возраст на основе идентификатора, чтобы у меня был «длинный формат» фрейма данных.
dput(данные):
structure(list(Code = c("MW68", "AW80", "EW40", "BW60", "Wn36",
"ZK45", "SI55", "MW68", "EW40", "DC06", NA, "IW28"), Age = c("52",
"26", "34", "26", "20", "35", NA, NA, NA, NA, NA, NA)), row.names = c(5L,
6L, 7L, 8L, 9L, 10L, 400L, 401L, 402L, 403L, 404L, 405L), class = "data.frame")
Input:
ID Age
AA23 18
BA53 32
AC13 55
AA23 NA
BA53 NA
AC13 NA
NA 23
AA23 NA
(the trick is that sometimes ID is NA)
And the desired output:
ID Age
AA23 18
BA53 32
AC13 55
AA23 18
BA53 32
AC13 55
NA 23
AA23 18
Заранее благодарю вас!
Комментарии:
1. Не могли бы вы привести пример того, как на самом деле выглядят данные в R? Я предполагаю, что в этих пустых полях будет что-то, например, NA или «»? Во-вторых, как может быть удостоверение
NA
личности ? Для меня в этом нет особого смысла. Если это так"NA"
, вы можете относиться к нему так же, как к другому тексту.2.
Code Sex Age GW35 1 29 BW44 0 21 DW07 1 20 MW36 1 33 NA 1 55 GW35 1 NA
Конечно, это из головы() Хорошо, это уродливо прямо здесь, я отредактировал это выше3. Вы можете использовать
dput(data)
данные или их подмножество для создания выходных данных, которые вы можете добавить в свой вопрос в виде кода, а другие могут копировать и вставлять, и в результате у вас будут примеры данных для работы4. Спасибо! Не знал о dput(), довольно полезно. Я добавил это выше. Но и здесь:
structure(list(Code = c("MW68", "AW80", "EW40", "BW60", "Wn36", "ZK45", "SI55", "MW68", "EW40", "DC06", NA, "IW28"), Age = c("52", "26", "34", "26", "20", "35", NA, NA, NA, NA, NA, NA)), row.names = c(5L, 6L, 7L, 8L, 9L, 10L, 400L, 401L, 402L, 403L, 404L, 405L), class = "data.frame")
5. Использование
dplyr
иtidyr
:data %>% group_by(Code) %>% fill(Age)
Ответ №1:
Вы также можете использовать функцию coalesce
, которая находит первое NA
значение и заменяет его значением, которое вы определяете, здесь мы хотели бы, чтобы это было первое значение каждой Age
переменной (группирующая переменная).:
library(dplyr)
df %>%
group_by(Code) %>%
mutate(across(Age, ~ coalesce(.x, first(.x))))
# A tibble: 12 x 2
# Groups: Code [10]
Code Age
<chr> <chr>
1 MW68 52
2 AW80 26
3 EW40 34
4 BW60 26
5 Wn36 20
6 ZK45 35
7 SI55 NA
8 MW68 52
9 EW40 34
10 DC06 NA
11 NA NA
12 IW28 NA
Комментарии:
1. Спасибо!!! Я потратил на это последние шесть часов, но вы справились с этим простым кодом. Сработало отлично 🙂
2. С удовольствием. Рад, что это помогло.
na.locf
функция из пакетаzoo
, упомянутого ранее г-ном @Крисом Рулеманном, также является очень хорошим и полезным решением в этих ситуациях. Просто имейте все это в виду и посмотрите, какой из них подойдет для вашей проблемы в будущем.
Ответ №2:
Я не совсем уверен, правильно ли я понял, что вы хотите сделать, но этот код здесь должен указывать, где находится Возраст NA
, и заполнять среднее значение возраста из других строк той же записью в коде. Очевидно, что это не удастся, если в коде есть значения, в которых нигде в таблице нет значения возраста. Если в разных строках с одним и тем же кодом имеются различные значения возраста, он заполнит среднее значение в этом примере, так как вы не указали, что делать в таком случае.
for(i in 1:nrow(data)){
if(!is.na(data$Code[i])){
if(is.na(data$Age[i])){
data$Age[i] <- mean(data$Age[data$Code == data$Code[i]], na.rm = TRUE)
}
}
}
Это пропускает строки с NA
в столбце кода.
Комментарии:
1. Спасибо! Это сработало 😀 ( получилось несколько NAN, которые мне пришлось потом заменить на NAs, но в остальном — все хорошо).
Ответ №3:
Вот решение, основанное на zoo
функции s na.locf
(«в случае NA последнее наблюдение перенесено вперед»): сначала вы группируетесь Code
, а затем mutate column
стареете using
and carrying the last non-
, если наблюдение NA перенесено вперед:
library(zoo)
data %>%
group_by(Code) %>%
mutate(Age = ifelse(is.na(Age), na.locf(Age), Age))
# A tibble: 12 x 2
# Groups: Code [10]
Code Age
<chr> <chr>
1 MW68 52
2 AW80 26
3 EW40 34
4 BW60 26
5 Wn36 20
6 ZK45 35
7 SI55 NA
8 MW68 52 # <- value `carried forward`
9 EW40 34 # <- value `carried forward`
10 DC06 NA
11 NA NA
12 IW28 NA