Как сделать двухосную гистограмму в R

Я пытаюсь визуально сравнить количество двух видов на одном графике в течение нескольких лет в R. Я видел этот график в Интернете и надеюсь создать что-то подобное в R, но не нашел в Интернете много полезного.

enter image description here

Мои данные:

> head(df2)
# A tibble: 6 x 4
# Groups:   Zone, Year [6]
   Year Zone      weighted_den weighted_den_carid
  <dbl> <fct>            <dbl>              <dbl>
1  2009 West           0.00109           0.485   
2  2009 Rankin         0                 0.0869  
3  2009 Whipray        0                 0.000176
4  2009 Crocodile      0                 0.0213  
5  2010 West           0.00245           2.26    
6  2010 Rankin         0                 0    

Моя попытка:

ggplot(df2, aes(x=Zone)) + 
  geom_bar(aes(y=weighted_den_carid), col = 'red') +
  geom_bar(aes(y=weighted_den), col = 'blue') +
  scale_y_continuous("Carid", sec.axis = sec_axis(~ . *100, name = "Cneb")) +
  facet_wrap(~Year)

формат dput моих данных:

dput(df) structure(list(Year = c(2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2014, 2014, 2014, 2014, 2014, 2014, 2014, 2014, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021), Zone = structure(c(3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L, 3L, 3L, 2L, 2L, 4L, 4L, 1L, 1L), .Label = c("Crocodile", "Rankin", "West", "Whipray"), class = "factor"), code = c("2009-West", "2009-West", "2009-Rankin", "2009-Rankin", "2009-Whipray", "2009-Whipray", "2009-Crocodile", "2009-Crocodile", "2010-West", "2010-West", "2010-Rankin", "2010-Rankin", "2010-Whipray", "2010-Whipray", "2010-Crocodile", "2010-Crocodile", "2011-West", "2011-West", "2011-Rankin", "2011-Rankin", "2011-Whipray", "2011-Whipray", "2011-Crocodile", "2011-Crocodile", "2012-West", "2012-West", "2012-Rankin", "2012-Rankin", "2012-Whipray", "2012-Whipray", "2012-Crocodile", "2012-Crocodile", "2013-West", "2013-West", "2013-Rankin", "2013-Rankin", "2013-Whipray", "2013-Whipray", "2013-Crocodile", "2013-Crocodile", "2014-West", "2014-West", "2014-Rankin", "2014-Rankin", "2014-Whipray", "2014-Whipray", "2014-Crocodile", "2014-Crocodile", "2015-West", "2015-West", "2015-Rankin", "2015-Rankin", "2015-Whipray", "2015-Whipray", "2015-Crocodile", "2015-Crocodile", "2016-West", "2016-West", "2016-Rankin", "2016-Rankin", "2016-Whipray", "2016-Whipray", "2016-Crocodile", "2016-Crocodile", "2017-West", "2017-West", "2017-Rankin", "2017-Rankin", "2017-Whipray", "2017-Whipray", "2017-Crocodile", "2017-Crocodile", "2018-West", "2018-West", "2018-Rankin", "2018-Rankin", "2018-Whipray", "2018-Whipray", "2018-Crocodile", "2018-Crocodile", "2019-West", "2019-West", "2019-Rankin", "2019-Rankin", "2019-Whipray", "2019-Whipray", "2019-Crocodile", "2019-Crocodile", "2020-West", "2020-West", "2020-Rankin", "2020-Rankin", "2020-Whipray", "2020-Whipray", "2020-Crocodile", "2020-Crocodile", "2021-West", "2021-West", "2021-Rankin", "2021-Rankin", "2021-Whipray", "2021-Whipray", "2021-Crocodile", "2021-Crocodile"), species = c("weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid", "weighted_den", "weighted_den_carid"), density = c(0.00109451560281117, 0.484952868327336, 0, 0.086948676470023, 0, 0.000175586458772299, 0, 0.0213370469869364, 0.00244750051380243, 2.25961874077752, 0, 0, 0, 0.00109652922201019, 0, 0, 0.00155162534766244, 1.87765191982742, 0, 0.0506693553371398, 0, 0.00888790576574783, 0, 0.000113921166552746, 0.00271835365647371, 1.43239056009749, 0, 0.000182039455286541, 0, 0, 0, 0.000561519490035231, 0.00225835591184498, 2.40719953239284, 0, 0.000388080206313915, 0, 0.00309583234733728, 0, 0.000815020765525142, 9.16873040427497e-05, 0.330946212564868, 0, 0.00121708105974097, 0, 0, 0, 0, 0.00120311020545607, 0.245785509346677, 0, 0, 0, 0, 0, 0.0170052902510473, 0.00331914172039662, 0.65236339593047, 0.0018818919255523, 0.00514144664157328, 0.00049840112185749, 0.00211954056631631, 0, 0.00202007130311886, 0.00419876411388295, 0.199634354821455, 0.000976084425739813, 0.104217100578605, 0.00017317664770464, 0.00103563821616542, 0.000231762069846282, 0.000115118681029652, 0.001688624458484, 0.112896098983775, 0.00221388120855345, 0.00851524454018168, 0.000145407848151758, 0.000434852081803272, 0, 0.000412676750124396, 0.00273638649319108, 0.267608818473059, 0.00332090562164444, 0.068723241681447, 0.000426749934946656, 0.00149987725304424, 0, 0.000192673737735322, 0.000951619776409427, 0.215338040060959, 0.000434586745104274, 0.0478934449975685, 0, 0.00150998374994783, 0, 0.00129010186017751, 0.00131030492673741, 0.300718374949211, 0.00110524705272365, 0.203148234839554, 0, 0.00205469524493215, 0, 0.00279004408491279)), row.names = c(NA, -104L), groups = structure(list( Zone = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), .Label = c("Crocodile", "Rankin", "West", "Whipray"), class = "factor"), Year = c(2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021), .rows = structure(list(7:8, 15:16, 23:24, 31:32, 39:40, 47:48, 55:56, 63:64, 71:72, 79:80, 87:88, 95:96, 103:104, 3:4, 11:12, 19:20, 27:28, 35:36, 43:44, 51:52, 59:60, 67:68, 75:76, 83:84, 91:92, 99:100, 1:2, 9:10, 17:18, 25:26, 33:34, 41:42, 49:50, 57:58, 65:66, 73:74, 81:82, 89:90, 97:98, 5:6, 13:14, 21:22, 29:30, 37:38, 45:46, 53:54, 61:62, 69:70, 77:78, 85:86, 93:94, 101:102), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list"))), row.names = c(NA, -52L), class = c("tbl_df", "tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", "tbl_df", "tbl", "data.frame"))

Вам нужно geom_col вместо geom_bar?

Allan Cameron 10.04.2022 18:46

На самом деле, geom_bar работает, я просто пока не могу правильно настроить масштабы плотины. ggplot (df2, aes (x = Zone)) + geom_bar (stat = «идентичность», aes (y = плотность, цвет = вид, альфа = вид, fill = вид), position = position_dodge (width = 1)) + scale_y_continuous (name = "C. neb Weighted Density", sec.axis = sec_axis(~ ./100, "Caridean Weighted Density")) + scale_alpha_manual(values ​​= c(0.7, 0.7)) + # Прозрачность цвета facet_wrap(~Year)

Nate 10.04.2022 18:48

Мне также пришлось преобразовать данные в «длинную версию» (weighted_den_carid и weighted_den теперь являются факторными уровнями под заголовком столбца, который я назвал «виды»). Их соответствующие значения находятся под столбцом «плотность».

Nate 10.04.2022 18:51

Я думаю, было бы довольно легко это исправить, если бы вы могли поделиться своими данными в формате dput — маленькой головы вашего фрейма данных на самом деле недостаточно, чтобы продемонстрировать решение.

Allan Cameron 10.04.2022 19:06

Пытаясь, я получаю сообщение об ошибке, говорящее, что это слишком много кода и недостаточно «деталей».

Nate 10.04.2022 19:17

Поместить его вне блока кода?

Allan Cameron 10.04.2022 19:19
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
1
6
35
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Сначала я создал воспроизводимый набор данных со случайными данными:

df <- data.frame(Year = rep(c(2009, 2010, 2011, 2012), 5),
                  Zone = rep(c("West", "Rankin", "Whipray", "Crocodile"), 5),
                  weighted_den = runif(20, 0, 1),
                  weighted_den_carid = runif(20, 0, 3))

После этого вы должны melt свои данные, используя следующий код:

library(reshape)
library(tidyverse)
df2 <- melt(df, id = c("Zone", "Year"))

И используйте следующий код для построения столбцов со второй осью Y:

df2 %>% ggplot(aes(x = Zone, y = value, fill = variable)) +
  geom_bar(stat = "identity", position = "dodge") +
  scale_y_continuous("Carid", sec.axis = sec_axis(~ . *100, name = "Cneb")) 

Выход:

enter image description here

Спасибо. Однако есть ли способ сохранить столбец «Год», чтобы я мог включить этот фрагмент кода ggplot -> «facet_wrap (~ Год)»? Кроме того, weighted_den должен быть примерно в 100 раз меньше, чем weighted_den_carid в df2.

Nate 10.04.2022 19:34

@Nate, я немного изменил код. Теперь вы также можете использовать столбец «Год». Я создал случайные данные, так что может быть, weighted_den не в 100 раз меньше.

Quinten 10.04.2022 19:47
Ответ принят как подходящий

С вашим выводом мы можем создать следующий код, который делает то, что вы просили, хотя я не уверен, насколько он эффективен в качестве визуализации:

tidyr::pivot_wider(df, names_from = species, values_from = density) %>%
ggplot(aes(x = as.numeric(Zone) - 0.125)) + 
  geom_col(aes(y = weighted_den, group = 1, fill = 'weighted_den'),
           width = 0.25) +
  geom_col(aes(x = as.numeric(Zone) + 0.125,
               y = weighted_den_carid / 100,
               fill = 'weighted_den_carid'), width =0.25) + 
  scale_x_continuous(breaks = 1:4, labels = levels(df$Zone)) +
  scale_y_continuous(sec.axis = sec_axis(trans = ~.x * 100,
                                         name = 'weighted_den_carid')) +
  facet_wrap(~Year, scales = 'free_y') +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90))

enter image description here

Да, это не так полезно, как визуальное представление, но нам было интересно посмотреть, будет ли плотность одного вида предсказывать плотность другого (очевидно, что ответ = не совсем, ха-ха). Спасибо, сэр!

Nate 10.04.2022 19:51

Ну что ж, это все хорошая наука, Нейт!

Allan Cameron 10.04.2022 19:53

Другие вопросы по теме