If I understand correctly, I would use tidyr
like this
library(tidyr)
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
# get data in tidy format
bin_tab <- iris %>%
select(Species, Sepal.Length, Petal.Width) %>%
mutate_if(is.numeric, cut, c(0, 1, 3, 5, 7, 9)) %>%
pivot_longer(cols = -Species)
glimpse(bin_tab)
#> Observations: 300
#> Variables: 3
#> $ Species <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa...
#> $ name <chr> "Sepal.Length", "Petal.Width", "Sepal.Length", "Petal....
#> $ value <fct> "(5,7]", "(0,1]", "(3,5]", "(0,1]", "(3,5]", "(0,1]", ...
# using aggregation in pivot function
res1 <- bin_tab %>%
pivot_wider(id_cols = Species,
names_from = c(name, value),
values_fn = list(value = length),
values_fill = list(value = 0))
res1
#> # A tibble: 3 x 6
#> Species `Sepal.Length_(~ `Petal.Width_(0~ `Sepal.Length_(~
#> <fct> <int> <int> <int>
#> 1 setosa 22 50 28
#> 2 versic~ 47 7 3
#> 3 virgin~ 37 0 1
#> # ... with 2 more variables: `Petal.Width_(1,3]` <int>,
#> # `Sepal.Length_(7,9]` <int>
# calculating bin number in tidy format then pivoting
bin_tab %>%
group_by_all() %>%
count() %>%
pivot_wider(id_cols = Species, names_from = c(name, value), values_from = n, values_fill =list(n = 0)) %>%
select(colnames(res1))
#> # A tibble: 3 x 6
#> # Groups: Species [3]
#> Species `Sepal.Length_(~ `Petal.Width_(0~ `Sepal.Length_(~
#> <fct> <int> <int> <int>
#> 1 setosa 22 50 28
#> 2 versic~ 47 7 3
#> 3 virgin~ 37 0 1
#> # ... with 2 more variables: `Petal.Width_(1,3]` <int>,
#> # `Sepal.Length_(7,9]` <int>
Created on 2019-09-23 by the reprex package (v0.3.0)