#r #spss
#r #spss
Вопрос:
Я хотел бы заменить NA значением из других строк на основе идентификатора. Я нашел похожие вопросы, но я не нашел решения своей проблемы.
Приведенная ниже часть таблицы
XCODE Age Sex ResultA ResultB ResultC
1 X001 12 2 2 3 4
2 X002 23 2 4 6 66
3 X003 NA NA NA NA NA
4 X004 32 1 1 7 3
5 X005 NA NA NA NA NA
6 X001 NA NA NA NA NA
7 X002 NA NA NA NA NA
8 X003 33 1 8 7 6
9 X004 NA NA NA NA NA
10 X005 55 2 8 8 8
У меня есть файл SPSS с более чем 6000 столбцами.
Я использовал
library(data.table)
setDT(dataset)[, Age:= Age[!is.na(Age)][1L] , by = XCODE]
но это хорошо только для одного столбца, и мне нужно иметь дело со многими столбцами.
Итак, как я могу выполнить приведенный выше код для всех столбцов?
Комментарии:
1. Легче ответить, если вы предоставите воспроизводимые данные и покажете другую таблицу, которая показывает, как вы хотите, чтобы это было.
2. Таким образом, всегда есть ровно одно не
NA
значение и одно (или больше?)NA
для каждой группы, верно?3. Почему тег SPSS — вы тоже ищете ответ в SPSS?
Ответ №1:
С помощью data.table
мы можем выбрать столбцы, которые мы хотим replace
library(data.table)
setDT(df)[, (2:ncol(df)) := lapply(.SD, function(x)
replace(x, is.na(x), x[!is.na(x)][1])) , XCODE]
df
# XCODE Age Sex ResultA ResultB ResultC
# 1: X001 12 2 2 3 4
# 2: X002 23 2 4 6 66
# 3: X003 33 1 8 7 6
# 4: X004 32 1 1 7 3
# 5: X005 55 2 8 8 8
# 6: X001 12 2 2 3 4
# 7: X002 23 2 4 6 66
# 8: X003 33 1 8 7 6
# 9: X004 32 1 1 7 3
#10: X005 55 2 8 8 8
Используя ту же логику в, dplyr
мы можем заменить NA
s первым значением группы, отличным от NA, для всех столбцов
library(dplyr)
df %>%
group_by(XCODE) %>%
mutate_all(~replace(., is.na(.), .[!is.na(.)][1]))
# XCODE Age Sex ResultA ResultB ResultC
# <fct> <int> <int> <int> <int> <int>
# 1 X001 12 2 2 3 4
# 2 X002 23 2 4 6 66
# 3 X003 33 1 8 7 6
# 4 X004 32 1 1 7 3
# 5 X005 55 2 8 8 8
# 6 X001 12 2 2 3 4
# 7 X002 23 2 4 6 66
# 8 X003 33 1 8 7 6
# 9 X004 32 1 1 7 3
#10 X005 55 2 8 8 8
Или только выбранные столбцы
cols <- c("Age", "Sex", "ResultA","ResultB")
df %>%
group_by(XCODE) %>%
mutate_at(vars(cols), ~ replace(., is.na(.), .[!is.na(.)][1]))
Комментарии:
1. я использовал
setDT(df)[, (2:ncol(df)) := lapply(.SD, function(x) replace(x, is.na(x), x[!is.na(x)][1])) , XCODE]
, и это отлично работает! Но теперь я хотел бы удалить дубликаты и оставить только один из каждого примера XCODE. Есть ли такая функция, которую я мог бы использовать с data.table?2. @l2archer под единицей вы имеете в виду первую из каждой
XCODE
? Вы можете попробовать выполнитьdf[!duplicated(df$XCODE), ]
после описанной выше операции.3. Но как тогда сохранить этот результат в data.table, чтобы я мог позже экспортировать в .xlss? Теперь я использую
options(java.parameters = "-Xmx1000m") library(WriteXLS) WriteXLS("dataset",ExcelFileName="D:/XCodeMerged50.xlsx",row.names=F,col.names=T)
4.
df1 <- df[!duplicated(df$XCODE), ]
и тогда вы можетеxlsx::write.xlsx(x = df1, file = "your.excelfile.xlsx",sheetName = "test")
или просто использоватьwrite.csv(df1, "test.csv")
5. Остается решить только одну вещь. Моя таблица данных основана на файле SPSS, в котором много меток для переменных. И теперь я пометил значения, например, в ячейке есть уровень информационного образования — средняя школа. И я бы предпочел получить необработанное значение (номер метки). Как изменить кодировку значений в таблице, чтобы получить необработанное, не помеченное значение?
Ответ №2:
Мы можем сгруппировать по XCODE
и использовать fill()
для заполнения NAS последними не-NA. В этом случае нам нужно заполнить в обоих направлениях. Также обратите внимание, что, поскольку вы заполняете все переменные, тогда можно использовать функцию everything()
library(tidyverse)
df %>%
group_by(XCODE) %>%
fill(everything()) %>%
fill(everything(), .direction = 'up')
что дает,
# A tibble: 10 x 6 # Groups: XCODE [5] XCODE Age Sex ResultA ResultB ResultC <fct> <int> <int> <int> <int> <int> 1 X001 12 2 2 3 4 2 X001 12 2 2 3 4 3 X002 23 2 4 6 66 4 X002 23 2 4 6 66 5 X003 33 1 8 7 6 6 X003 33 1 8 7 6 7 X004 32 1 1 7 3 8 X004 32 1 1 7 3 9 X005 55 2 8 8 8 10 X005 55 2 8 8 8