Создайте новый столбец только с не-NA в определенных столбцах [R]

#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"