Project a horizontal dendrogram - dendrogram

Folks:
Is there a way to make a dendrogram generated from function like hclust() horizontal, without using the function as.dendrogram().
So not to loose the enhancement code (i.e, rect.hclust, xlab, ylab, etc.) developed for the original hclust dendrogram?
Thanks!

You can use the dendextend R package to get all of this functionality in more in dendrograms.
For example
library(dendextend)
dend <- USArrests %>%
dist() %>%
hclust(method = "ave") %>%
as.dendrogram() %>% hang.dendrogram() %>%
color_branches(k = 5)
par(mar = c(2,2,1,8))
plot(dend, horiz = T)
rect.dendrogram(dend, k = 3, horiz = T)
More details:
https://cran.r-project.org/web/packages/dendextend/vignettes/dendextend.html

Related

I’m a R beginner and having difficulty with the Divvy bike Trips capstone project: code chunks to remove NAs:

I can't figure out where the problem is, but i don't have values on my "MIN' and i still have "NA" on my graph after using some codes like na.mit() and drop_na,pictures and code chunks are slated below:
aggregate(all_trips_v2$ride_length ~ all_trips_v2$member_casual, FUN = mean)
aggregate(all_trips_v2$ride_length ~ all_trips_v2$member_casual, FUN = median)
aggregate(all_trips_v2$ride_length ~ all_trips_v2$member_casual, FUN = max)
aggregate(all_trips_v2$ride_length ~ all_trips_v2$member_casual, FUN = min)
code to get min value
all_trips_v2 %>%
mutate(weekday = wday(started_at, label = TRUE)) %>%
group_by(member_casual, weekday) %>%
summarise(number_of_rides = n(),average_duration = mean(ride_length)) %>%
arrange(member_casual,weekday)
I tried using these codes: na.omit() and print(df %>% drop_na()) ](https://i.stack.imgur.com/aW0kC.jpg)
I tried using these codes: na.omit() and print(df %>% drop_na()) to remove the NA values but it's not working.
For mean in summarize, after the variable name add , na.rm = TRUE . –
Elin
Feb 1 at 5:50
all_trips_v2 %>%
mutate(weekday = wday(started_at, label = TRUE)) %>%
group_by(member_casual, weekday) %>%
summarise(number_of_rides = n(),average_duration = mean(ride_length,na.rm = TRUE)) %>%
arrange(member_casual,weekday)

Add space argument to facet_wrap

facet_wrap() has been recognized for not having a space = "free" argument (https://github.com/tidyverse/ggplot2/issues/2933). This can causes spacing issues on the y-axis of plots.
Create the above figure using the following code:
library(tidyverse)
p <-
mtcars %>%
rownames_to_column() %>%
ggplot(aes(x = disp, y = rowname)) + geom_point() +
facet_wrap(~ carb, ncol = 1, scales = "free_y")
facet_grid on the other hand has a space = "free" argument. Allowing for nice y-axis spacing.
Create the above figure using the following code:
p <-
mtcars %>%
rownames_to_column() %>%
ggplot(aes(x = disp, y = rowname)) + geom_point() +
facet_grid(carb ~ ., scales = "free_y", space = "free_y")
The issue with this is that the label is on the side, not the top. I sometimes have longer facet labels and few rows in the facet. This means the facet label gets cut off.
There is a solution from the ggforce package (comment by ilarischeinin on https://github.com/tidyverse/ggplot2/issues/2933).
p <-
mtcars %>%
rownames_to_column() %>%
ggplot(aes(x = disp, y = rowname)) + geom_point()
p + ggforce::facet_col(vars(carb), scales = "free_y", space = "free")
But, there are limitations leaving ggplot2. For example, I ultimately want a two column figure, and this functionality does not seem possible with ggforce. Is there any way to produce the same result using facet_wrap() so that I can utilize the ncol() argument?
Here is a potential workaround based on https://stackoverflow.com/a/29022188/12957340 :
library(tidyverse)
library(gtable)
library(grid)
p1 <- mtcars %>%
rownames_to_column() %>%
ggplot(aes(x = disp, y = rowname)) + geom_point() +
facet_grid(carb ~ ., scales = "free_y", space = "free_y") +
theme(panel.spacing = unit(1, 'lines'),
strip.text.y = element_text(angle = 0))
gt <- ggplotGrob(p1)
panels <-c(subset(gt$layout, grepl("panel", gt$layout$name), se=t:r))
for(i in rev(panels$t-1)) {
gt = gtable_add_rows(gt, unit(0.5, "lines"), i)
}
panels <-c(subset(gt$layout, grepl("panel", gt$layout$name), se=t:r))
strips <- c(subset(gt$layout, grepl("strip-r", gt$layout$name), se=t:r))
stripText = gtable_filter(gt, "strip-r")
for(i in 1:length(strips$t)) {
gt = gtable_add_grob(gt, stripText$grobs[[i]]$grobs[[1]], t=panels$t[i]-1, l=5)
}
gt = gt[,-6]
for(i in panels$t) {
gt$heights[i-1] = unit(0.8, "lines")
gt$heights[i-2] = unit(0.2, "lines")
}
grid.newpage()
grid.draw(gt)
Created on 2021-12-15 by the reprex package (v2.0.1)
It's not clear to me what you mean by "I ultimately want a two column figure", but if you can come up with an example to illustrate your 'ultimate' expected outcome I can try to adapt this approach and see if it will work or not.

Barplot of percentages by groups in ggplot2

So, I've done my searches but cannot find the solution to this problem i have with a bar plot in ggplot.
I'm trying to make the bars be in percentage of the total number of cases in each group in grouping variable 2.
Right now i have it visualising the number of counts,
Dataframe = ASAP
Grouping variable 1 - cc_groups (seen in top of the graph)
(counts number of cases within a range (steps of 20) in a score from 0-100.)
grouping variable 2 - asap
( binary variable with either intervention or control, number of controls and interventions are not the same)
Initial code
``` r
ggplot(ASAP, aes(x = asap, fill = asap)) + geom_bar(position = "dodge") +
facet_grid(. ~ cc_groups) + scale_fill_manual(values = c("red",
"darkgray"))
#> Error in ggplot(ASAP, aes(x = asap, fill = asap)): could not find function "ggplot"
```
Created on 2020-05-19 by the reprex package (v0.3.0)
this gives me the following graph which is a visualisation of the counts in each subgroup.
enter image description here
I have manually calculated the different percentages that actually needs to be visualised:
table_groups <- matrix(c(66/120,128/258,34/120,67/258,10/120,30/258,2/120,4/258,0,1/258,8/120,28/258),ncol = 2, byrow = T)
colnames(table_groups) <- c("ASAP","Control")
rownames(table_groups) <- c("0-10","20-39","40-59","60-79","80-99","100")
ASAP Control
0-10 0.55000 0.496124
20-39 0.28333 0.259690
40-59 0.08333 0.116279
60-79 0.01667 0.015504
80-99 0.00000 0.003876
100 0.06667 0.108527
When i use the solution provided by Stefan below (which was an excellent answer but didn't do the actual trick. i get the following output
``` r
ASAP %>% count(cc_groups, asap) %>% group_by(cc_groups) %>% mutate(pct = n/sum(n)) %>%
ggplot(aes(x = asap, y = pct, fill = asap)) + geom_col(position = "dodge") +
facet_grid(~cc_groups) + scale_fill_manual(values = c("red",
"darkgray"))
#> Error in ASAP %>% count(cc_groups, asap) %>% group_by(cc_groups) %>% mutate(pct = n/sum(n)) %>% : could not find function "%>%"
```
<sup>Created on 2020-05-19 by the [reprex package](https://reprex.tidyverse.org) (v0.3.0)</sup>
enter image description here
whereas (when i go analogue) id like it to show the percentages as above like this.
enter image description here
Im SO sorry about that drawing.. :) and reprex kept feeding me errors, im sure im using it incorrectly.
The easiest way to achieve this is via aggregating the data before plotting, i.e. manually computing counts and percentages:
library(ggplot2)
library(dplyr)
ASAP %>%
count(cc_groups, asap) %>%
group_by(asap) %>%
mutate(pct = n / sum(n)) %>%
ggplot(aes(x = asap, y = pct, fill=asap)) +
geom_col(position="dodge")+
facet_grid(~cc_groups)+
scale_fill_manual(values = c("red","darkgray"))
Using ggplot2::mpg as example data:
library(ggplot2)
library(dplyr)
# example data
mpg2 <- mpg %>%
filter(cyl %in% c(4, 6)) %>%
mutate(cyl = factor(cyl))
# Manually compute counts and percentages
mpg3 <- mpg2 %>%
count(class, cyl) %>%
group_by(class) %>%
mutate(pct = n / sum(n))
# Plot
ggplot(mpg3, aes(x = cyl, y = pct, fill = cyl)) +
geom_col(position = "dodge") +
facet_grid(~ class) +
scale_fill_manual(values = c("red","darkgray"))
Created on 2020-05-18 by the reprex package (v0.3.0)

Adding percentage labels to a barplot with y-axis 'count' in R

I'd like to add percentage labels per gear to the bars but keep the count y-scale.
E.g. 10% of all 'gear 3' are '4 cyl'
library(ggplot)
ds <- mtcars
ds$gear <- as.factor(ds$gear)
p1 <- ggplot(ds, aes(gear, fill=gear)) +
geom_bar() +
facet_grid(cols = vars(cyl), margins=T)
p1
Ideally only in ggplot, wihtout adding dplyr or tidy. I found some of these solutions but then I get other issues with my original data.
EDIT: Suggestions that this is a duplicate from:
enter link description here
I saw this also earlier, but wasn't able to integrate that code into what I want:
# i just copy paste some of the code bits and try to reconstruct what I had earlier
ggplot(ds, aes(gear, fill=gear)) +
facet_grid(cols = vars(cyl), margins=T) +
# ..prop.. meaning %, but i want to keep the y-axis as count
geom_bar(aes(y = ..prop.., fill = factor(..x..)), stat="count") +
# not sure why, but I only get 100%
geom_text(aes( label = scales::percent(..prop..),
y= ..prop.. ), stat= "count", vjust = -.5)
The issue is that ggplot doesn't know that each facet is one group. This very useful tutorial helps with a nice solution. Just add aes(group = 1)
P.S. At the beginning, I was often quite reluctant and feared myself to manipulate my data and pre-calculate data frames for plotting. But there is no need to fret! It is actually often much easier (and safer!) to first shape / aggregate your data into the right form and then plot/ analyse the new data.
library(tidyverse)
library(scales)
ds <- mtcars
ds$gear <- as.factor(ds$gear)
First solution:
ggplot(ds, aes(gear, fill = gear)) +
geom_bar() +
facet_grid(cols = vars(cyl), margins = T) +
geom_text(aes(label = scales::percent(..prop..), group = 1), stat= "count")
edit to reply to comment
Showing percentages across facets is quite confusing to the reader of the figure and I would probably recommend against such a visualization. You won't get around data manipulation here. The challenge is here to include your "facet margin". I create two summary data frames and bind them together.
ds_count <-
ds %>%
count(cyl, gear) %>%
group_by(gear) %>%
mutate(perc = n/sum(n)) %>%
ungroup %>%
mutate(cyl = as.character(cyl))
ds_all <-
ds %>%
count(cyl, gear) %>%
group_by(gear) %>%
summarise(n = sum(n)) %>%
mutate(cyl = 'all', perc = 1)
ds_new <- bind_rows(ds_count, ds_all)
ggplot(ds_new, aes(gear, fill = gear)) +
geom_col(aes(gear, n, fill = gear)) +
facet_grid(cols = vars(cyl)) +
geom_text(aes(label = scales::percent(perc)), stat= "count")
IMO, a better way would be to simply swap x and facetting variables. Then you can use ggplots summarising function as above.
ggplot(ds, aes(as.character(cyl), fill = gear)) +
geom_bar() +
facet_grid(cols = vars(gear), margins = T) +
geom_text(aes(label = scales::percent(..prop..), group = 1), stat= "count")
Created on 2020-02-07 by the reprex package (v0.3.0)

R: expss package: possible to automate table generation?

I'm looking for a way to automate table generation using the expss package in an attempt to move from spss to R.
I think this should be simple but I seem to miss something...
I only define a few different tables based on the question type.
Eg. the table for single respons looks like below
banner <- d %>% tab_cols(total(),Q2.banner,Q3.banner)
banner %>%
tab_cells (Q1) %>%
tab_stat_cases(total_row_position = c("above"),label = 'N') %>%
tab_stat_cpct(total_row_position = c("none"), label = '%') %>%
tab_pivot (stat_position = "inside_rows") %>%
drop_c () %>%
custom_format()
I'm looking for a function in which I only have to specify the variable
Eg .
Table1 = function (Q, banner) {
banner %>%
tab_cells (Q) %>%
tab_stat_cases(total_row_position = c("above"),label = 'N') %>%
tab_stat_cpct(total_row_position = c("none"), label = '%') %>%
tab_pivot (stat_position = "inside_rows") %>%
drop_c () %>%
custom_format()
}
Ideally I would like to add a table title as well.
I'm running the table books in R Notebook.
Any other tips to automate table generation are all welcome.
Thanks for all help,
michaëla
There is a rather universal solution for working with non-standard evaluation - eval.parent(substitute(...)). In your case it looks like this:
Table1 = function (Q, banner) {
eval.parent(substitute(
{
banner %>%
tab_cells (Q) %>%
tab_stat_cases(total_row_position = c("above"),label = 'N') %>%
tab_stat_cpct(total_row_position = c("none"), label = '%') %>%
tab_pivot (stat_position = "inside_rows") %>%
drop_c () %>%
custom_format()
}
))
}