#r #for-loop #ggplot2
#r #для цикла #ggplot2
Вопрос:
Я хочу просмотреть шесть похожих фреймов данных и распечатать шесть графиков, используя ggplot.
Мой код работает, когда я запускаю графики отдельно, но я не могу заставить ggplot запускаться шесть раз, используя цикл for. Мои шесть фреймов данных — это шесть животных, перечисленных в gg_pets.
cat <- data.frame(Breed = c("American Shorthair","Ragdoll","Persian","Sphynx","Maine Coon"),
Longevity = c("17","19","15","17","20"))
dog <- data.frame(Breed = c("Havanese","Bulldog","Beagle","Chihuahua","Poodle"),
Longevity = c("20","11","12","15","16"))
#etc for types of birds, fish, snakes, and ferrets
#the following works
plot <- ggplot(data = cat, aes(x = Breed, y = Longevity, fill = Breed))
geom_bar(stat = "identity", position = position_dodge())
xlab("Breed")
ylab("Longevity")
ggtitle("cat")
geom_text(aes(label = Longevity), vjust = -0.3, color = "black", size = 3.5)
theme(axis.line = element_line(color = "black"), axis.text = element_text(color = "black"),
legend.position = "none", plot.title = element_text(hjust = .5),
panel.grid.minor = element_blank(), panel.grid.major = element_blank(),
panel.border = element_rect(color = "black", fill = NA, size = 0.8),
panel.background = element_rect(fill = NA), text = element_text(size=10))
print(plot)
gg_pets <- c("cat","dog","bird","fish","snake","ferret")
#the following does not work
for (i in 1:length(gg_pets)){
plot <- ggplot(data = [i], aes(x = Breed, y = Longevity, fill = Breed))
geom_bar(stat = "identity", position = position_dodge())
xlab("Breed")
ylab("Longevity")
ggtitle([i])
geom_text(aes(label = Longevity), vjust = -0.3, color = "black", size = 3.5)
theme(axis.line = element_line(color = "black"), axis.text = element_text(color = "black"),
legend.position = "none", plot.title = element_text(hjust = .5),
panel.grid.minor = element_blank(), panel.grid.major = element_blank(),
panel.border = element_rect(color = "black", fill = NA, size = 0.8),
panel.background = element_rect(fill = NA), text = element_text(size=10))
print(plot)
}
Ответ №1:
В вашем примере gg_pets — это просто вектор строк. Вам необходимо объединить фреймы данных, чтобы выполнить итерацию по ним в цикле for. Вы можете сделать это с помощью списка. Следующим образом. Вы можете использовать имена элементов в качестве заголовка.
...
gg_pets <- list(cat=cat, dog=dog)
#the following does not work
for (i in 1:length(gg_pets)) {
plot <- ggplot(data = gg_pets[[i]], aes(x = Breed, y = Longevity, fill = Breed))
geom_bar(stat = "identity", position = position_dodge())
xlab("Breed")
ylab("Longevity")
ggtitle(names(gg_pets)[i])
geom_text(aes(label = Longevity), vjust = -0.3, color = "black", size = 3.5)
theme(axis.line = element_line(color = "black"), axis.text = element_text(color = "black"),
legend.position = "none", plot.title = element_text(hjust = .5),
panel.grid.minor = element_blank(), panel.grid.major = element_blank(),
panel.border = element_rect(color = "black", fill = NA, size = 0.8),
panel.background = element_rect(fill = NA), text = element_text(size=10))
print(plot)
}
Комментарии:
1. Это идеально, спасибо. Как я могу отобразить все шесть фигур в одном окне? Добавление
par(mfrow = c(2,3))
перед циклом for и только внутри цикла for не работает.2. @Bex также сохраняет графики цикла for в списке. ` графики <- list() для (i в 1: длина (gg_pets)) { графики[[i]] <- ggplot(данные = gg_pets[[i]], … ` Затем используйте
grid.arrange
из пакета gridExtra, чтобы соединить их по своему усмотрению. Вот пример:gridExtra::grid.arrange(plots[[1]], plots[[2]], plots[[1]], plots[[2]], layout_matrix = rbind(c(1,2),c(3,4)))
Ответ №2:
Я думаю, вам нужно
ggplot(data = get(i), ...)
но, вероятно, было бы более идиоматичным / лучшей практикой поместить ваши наборы данных в именованный список ( my_data_list <- list(cat=cat, dog=dog, ...)
или даже my_data_list <- mget(gg_pets)
) и использовать data = my_data_list[[i]]
…
Ответ №3:
Альтернативой list
подходу, упомянутому в других ответах, было бы сначала иметь все в одном и том же data.frame
, поскольку, по-видимому, все таблицы имеют одинаковые переменные; а затем иметь еще одну переменную, указывающую, какому типу домашних животных соответствует наблюдение. Следующим образом:
pets_df <- bind_rows(cat %>% add_column(pet = 'cat'),
dog %>% add_column(pet = 'dog'))
> pets_df
Breed Longevity pet
1 American Shorthair 17 cat
2 Ragdoll 19 cat
3 Persian 15 cat
4 Sphynx 17 cat
5 Maine Coon 20 cat
6 Havanese 20 dog
7 Bulldog 11 dog
8 Beagle 12 dog
9 Chihuahua 15 dog
10 Poodle 16 dog
Затем на каждой итерации цикла вам нужно фильтровать только один data.frame
. Например:
for (i in 1:length(gg_pets)) {
plot <- ggplot(data = filter(pets_df, pet == gg_pets[i]),
aes(x = Breed, y = Longevity, fill = Breed))
geom_bar(stat = "identity", position = position_dodge())
xlab("Breed")
ylab("Longevity")
ggtitle(gg_pets[i])
geom_text(aes(label = Longevity), vjust = -0.3, color = "black", size = 3.5)
theme(axis.line = element_line(color = "black"), axis.text = element_text(color = "black"),
legend.position = "none", plot.title = element_text(hjust = .5),
panel.grid.minor = element_blank(), panel.grid.major = element_blank(),
panel.border = element_rect(color = "black", fill = NA, size = 0.8),
panel.background = element_rect(fill = NA), text = element_text(size=10))
print(plot)
}