Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the first non-NA element in a row

Tags:

r

dplyr

I have a dataframe where every row should contains mostly "No response" values (-1). I'd like to get the first value of every row that is not -1, preferably using something tidy-friendly.

# A tibble: 3,222 x 10
   tracc1 tracc2 tracc3 tracc4 tracc5 tracc6 tracc7 tracc8 tracc9 tracc10
   <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  
 1 1      -1     -1     -1     -1     -1     7      -1     -1     -1     
 2 1      -1     -1     -1     -1     -1     -1     -1     -1     -1     
 3 1      -1     -1     -1     -1     -1     -1     -1     -1     -1     
 4 1      -1     -1     -1     -1     -1     -1     -1     -1     -1     
 5 1      -1     -1     -1     -1     -1     -1     -1     -1     -1     
 6 1      -1     -1     -1     -1     -1     -1     -1     -1     -1     
 7 1      -1     -1     -1     -1     -1     -1     -1     -1     -1     
 8 1      -1     -1     -1     -1     -1     -1     -1     -1     -1     
 9 -1     -1     3      -1     -1     -1     -1     -1     -1     -1     
10 1      -1     -1     -1     -1     -1     -1     -1     -1     -1     
# ...

I was able to use dpylr::unite to combine all the columns, but problems arise when a single row has multiple valid responses. In the example below, row one should yield 1 rather than 17.

> df %>%
    mutate_at(vars(starts_with("tracc")),
              function(t) {if_else(t < 0,"",t)}) %>%
    unite("tracc",starts_with("tracc"),sep = "", na.rm = TRUE)
# A tibble: 3,222 x 1
   tracc
   <chr>
 1 17
 2 1
 3 1
 4 1
 5 1
 6 1
 7 1
 8 1
 9 3
10 1
# ...
like image 278
jane Avatar asked Dec 02 '22 09:12

jane


2 Answers

Try this simple code:

apply(df, 1, function(x) x[x != -1][1])

It parallelly applies to each row.

like image 149
Vitali Avagyan Avatar answered Dec 28 '22 23:12

Vitali Avagyan


One dplyr option could be:

df %>%
 mutate_all(~ replace(., . == "-1", NA_integer_)) %>%
 transmute(tracc = coalesce(!!!.))

   tracc
1      1
2      1
3      1
4      1
5      1
6      1
7      1
8      1
9      3
10     1

An option since dplyr 1.0.0 could be:

df %>%
 transmute(tracc = Reduce(coalesce, across(everything(), ~ replace(., . == "-1", NA_integer_))))
like image 39
tmfmnk Avatar answered Dec 29 '22 00:12

tmfmnk