JoB
JoB

Reputation: 41

How to add a column that counts values of another column

I'm not very familiar with the R-environment so far and I'm struggling with the following..:

df <- tibble(x= c(1.12, 4.12,4.64, NA, NA, 0.72), 
             y= c(8.92, 14.9, 3.2, NA, NA, NA))

I'd like to add two new columns that contain the number of cases of x/y.

I've already tried this which gives me the number but I don't know how to add this to the df-table.

nr <- colSums(!is.na(df))

Or is there maybe an easier way by using mutate()?

Thanks a lot !

Upvotes: 1

Views: 70

Answers (5)

akrun
akrun

Reputation: 886998

With tidyverse, one option would be uncount and expand the already created vector and bind with the existing dataset

library(dplyr)
library(tidyr)
library(stringr)
as.list(nr) %>% 
     as_tibble %>% 
     uncount(nrow(df)) %>% 
     rename_all(~ str_c(., '_case')) %>%
     bind_cols(df, .)
# A tibble: 6 x 4
#      x     y x_case y_case
#  <dbl> <dbl>  <dbl>  <dbl>
#1  1.12  8.92      4      3
#2  4.12 14.9       4      3
#3  4.64  3.2       4      3
#4 NA    NA         4      3
#5 NA    NA         4      3
#6  0.72 NA         4      3

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388862

Do you really want that information in the table as new column?

Here is one way using the already calculated nr

df[paste0(names(df), "_case")] <- as.list(nr)
df
# A tibble: 6 x 4
#      x     y x_case y_case
#  <dbl> <dbl>  <dbl>  <dbl>
#1  1.12  8.92      4      3
#2  4.12 14.9       4      3
#3  4.64  3.2       4      3
#4 NA    NA         4      3
#5 NA    NA         4      3
#6  0.72 NA         4      3

Or more generally,

df[paste0(names(df), "_case")] <- as.list(colSums(!is.na(df)))

Upvotes: 0

Bulat
Bulat

Reputation: 6969

data.table option:

library(data.table)
dt <- data.table(
  x= c(1.12, 4.12,4.64, NA, NA, 0.72), 
  y= c(8.92, 14.9, 3.2, NA, NA, NA)
)

dt[, x.cases := sum(!is.na(x))]
dt[, y.cases := sum(!is.na(y))]

# to apply same transformation to multiple colums:

cols <- c("x", "y")
out_cols = paste(cols, "cases", sep = ".")
dt[, c(out_cols) := lapply(.SD, function(x) sum(!is.na(x))), .SDcols = cols]

Upvotes: 1

yarnabrina
yarnabrina

Reputation: 1656

If you want to do it using mutate, try with mutate_all variant:

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

df <- tibble(x = c(1.12, 4.12,4.64, NA, NA, 0.72), 
             y = c(8.92, 14.9, 3.2, NA, NA, NA))

df %>%
  mutate_all(.funs = list(no_cases = ~ sum(!is.na(x = .))))
#> # A tibble: 6 x 4
#>       x     y x_no_cases y_no_cases
#>   <dbl> <dbl>      <int>      <int>
#> 1  1.12  8.92          4          3
#> 2  4.12 14.9           4          3
#> 3  4.64  3.2           4          3
#> 4 NA    NA             4          3
#> 5 NA    NA             4          3
#> 6  0.72 NA             4          3

Hope this helps.

Upvotes: 0

Lennyy
Lennyy

Reputation: 6132

Do you need this?

df <- tibble(x= c(1.12, 4.12,4.64, NA, NA, 0.72), 
             y= c(8.92, 14.9, 3.2, NA, NA, NA))


df$xcases <- sum(!is.na(df$x))
df$ycases <- sum(!is.na(df$y))
df

      x     y xcases ycases
  <dbl> <dbl>  <int>  <int>
1  1.12  8.92      4      3
2  4.12 14.9       4      3
3  4.64  3.2       4      3
4 NA    NA         4      3
5 NA    NA         4      3
6  0.72 NA         4      3

Upvotes: 2

Related Questions