James Prentice
James Prentice

Reputation: 55

R, 3-way table, how to order

I am trying to order a table that has 3 variables, commonly known as a 3-way table.

I have attached a picture of the structure of the table the replicable code will produce.

3-waytable

Is it possible to order this table in a logical way, despite the fact it is essentially split into three sections/groups? For instance, could you order by the column "No" or the column "Yes" based on the values? For example, when ordering "No" England would be ordered as "Sertosa" (7), Virginica (8), Versicolour (16). Wales would be ordered Versicolor (11), Setoda (12), Virginica... and so on for each section of the table.

#Replicable code using the Iris data built into R:

Data <- iris
Data $ var2 <- Data $ Species
Data $ var2 <- sample(Data $ var2)
Data $ var3 <- Data $ Species
Data $ var3 <- sample(Data $ var3)
#making the example clearer
library(plyr)
Data $ var2 <- revalue(Data $ var2, c("setosa"="No", "versicolor"="No","virginica" ="Yes")) 
Data $ var3 <- revalue(Data $ var3, c("setosa"="England", "versicolor"="Wales","virginica" ="Scotland")) 
#3-way Table:
df <- table(Data $ Species, Data $ var2, Data $ var3)
df

Kind Regards, James Prentice, a person trying to get to grips with R.

Upvotes: 3

Views: 148

Answers (1)

Brenton M. Wiernik
Brenton M. Wiernik

Reputation: 1316

You should avoid using table() and array() in R, as they are hard to work with. Also, I recommend you focus on learning dplyr, rather than plyr, as plyr is no longer maintained.

Instead of using table(), work directly with the original data frame:

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
Data <- iris
Data$Living <- sample(c("No", "Yes"), size = nrow(Data), replace = TRUE)
Data$Country <- sample(c("England", "Wales", "Scotland"), size = nrow(Data), replace = TRUE)

# Results in one data frame
Data %>%
  group_by(Country, Species) %>%
  summarize(Yes = sum(Living == "Yes"), No = sum(Living == "No")) %>%
  ungroup() %>% 
  arrange(Country, Yes) 
#> `summarise()` has grouped output by 'Country'. You can override using the `.groups` argument.
#> # A tibble: 9 x 4
#>   Country  Species      Yes    No
#>   <chr>    <fct>      <int> <int>
#> 1 England  virginica      2     8
#> 2 England  versicolor     7    15
#> 3 England  setosa        14     5
#> 4 Scotland setosa         5    14
#> 5 Scotland virginica      6    12
#> 6 Scotland versicolor     9     8
#> 7 Wales    setosa         4     8
#> 8 Wales    versicolor     5     6
#> 9 Wales    virginica     14     8

# Results in a list of data frames 
Data %>%
  group_by(Country, Species) %>%
  summarize(Yes = sum(Living == "Yes"), No = sum(Living == "No")) %>%
  ungroup() %>% 
  arrange(Country, Yes) %>%
  split(., .$Country)
#> `summarise()` has grouped output by 'Country'. You can override using the `.groups` argument.
#> $England
#> # A tibble: 3 x 4
#>   Country Species      Yes    No
#>   <chr>   <fct>      <int> <int>
#> 1 England virginica      2     8
#> 2 England versicolor     7    15
#> 3 England setosa        14     5
#> 
#> $Scotland
#> # A tibble: 3 x 4
#>   Country  Species      Yes    No
#>   <chr>    <fct>      <int> <int>
#> 1 Scotland setosa         5    14
#> 2 Scotland virginica      6    12
#> 3 Scotland versicolor     9     8
#> 
#> $Wales
#> # A tibble: 3 x 4
#>   Country Species      Yes    No
#>   <chr>   <fct>      <int> <int>
#> 1 Wales   setosa         4     8
#> 2 Wales   versicolor     5     6
#> 3 Wales   virginica     14     8

Created on 2021-06-01 by the reprex package (v2.0.0)

Upvotes: 4

Related Questions