#r #apply #na
#r #применить #na
Вопрос:
У меня есть следующая структура данных…
> data <- data.frame(txt = paste0("f", 1:8),
a = c(NA, NA, NA, "A", "B", "A", NA, "C"),
b = c("D", "A", "C", NA, NA, NA, NA, NA),
c = c(NA, NA, NA, NA, NA, NA, "C", NA))
> data
# txt a b c
# 1 f1 <NA> D <NA>
# 2 f2 <NA> A <NA>
# 3 f3 <NA> C <NA>
# 4 f4 A <NA> <NA>
# 5 f5 B <NA> <NA>
# 6 f6 A <NA> <NA>
# 7 f7 <NA> <NA> C
# 8 f8 C <NA> <NA>
… и я хочу создать новый столбец, содержащий значение этих столбцов, отличных от NA (теоретически, только один столбец).
> data$tmp <- sapply(1:nrow(data), function(i) gsub("NA", "", paste(as.data.frame(data[i,-1]), collapse = "")))
> data
# txt a b c tmp
# 1 f1 <NA> D <NA> D
# 2 f2 <NA> A <NA> A
# 3 f3 <NA> C <NA> C
# 4 f4 A <NA> <NA> A
# 5 f5 B <NA> <NA> B
# 6 f6 A <NA> <NA> A
# 7 f7 <NA> <NA> C C
# 8 f8 C <NA> <NA> C
Этот код, похоже, работает так, как я хочу, но у меня миллионы строк, и он ооочень медленный … кто-нибудь может помочь мне найти лучшее решение, пожалуйста? Заранее спасибо.
Ответ №1:
Следующее работает, если в строке есть только одно значение, отличное от NA:
data$tmp = data[!is.na(data)]
Комментарии:
1. Да, очень просто и полезно, большое спасибо. Я забыл упомянуть, что у меня также есть текстовый столбец, который я не хочу рассматривать, и он сбивает все ваши ответы…
2. попробуйте: data$tmp = data[!is.na (данные[, -i])] # Где i — индекс столбца, который вы хотите игнорировать.
3. Возможно, я делаю что-то неправильно, но я получаю эту ошибку:
Error in $<-.data.frame(*tmp*, tmp, value = c("f4", "f5", "f6", "f8", : replacement has 12 rows, data has 8
… сdata$tmp = data[!is.na(data[,-1])]
Ответ №2:
В случае, если нужно выбрать только один столбец, возможно, использование подмножества матрицы быстрее:
data$tmp <- data[matrix(c(seq_len(nrow(data)),
apply(!is.na(data), 1, which.max)), ncol=2)]
Или с использованием подхода от @Ventrilocus
tt <- t(data)
data$tmp <- tt[!is.na(tt)]
Комментарии:
1. Большое спасибо за ваш быстрый ответ, я отредактировал свой вопрос, потому что у меня также есть текстовый столбец, который я не хочу рассматривать. Еще раз спасибо.
Ответ №3:
Будет ли это работать:
library(dplyr)
data %>% mutate(tmp = coalesce(a,b,c))
a b c tmp
1 <NA> D <NA> D
2 <NA> A <NA> A
3 <NA> C <NA> C
4 A <NA> <NA> A
5 B <NA> <NA> B
6 A <NA> <NA> A
7 <NA> <NA> C C
8 C <NA> <NA> C
Комментарии:
1. Хороший (и простой) ответ, спасибо… и есть ли способ рассмотреть эти столбцы без их записи?? (потому что я обычно делаю a
grep
, чтобы найти свои столбцы).2. @jgarces, посмотри, работает ли это: data %>% mutate(tmp = do.call(объединение, данные))
3. Отлично, я отлично работаю! Мне пришлось подстроиться под свои данные, но
do.call(coalesce, data)
я сделал то, что хотел!
Ответ №4:
Мы можем использовать row/column
индексацию с max.col
data$tmp <- data[-1][cbind(seq_len(nrow(data)), max.col(!is.na(data[-1]), 'first'))]
data$tmp
#[1] "D" "A" "C" "A" "B" "A" "C" "C"