Контролирайте ширините на колоните в графика ggplot2 със серия и непоследователни данни

В изкуствените данни, които създадох за MWE по-долу, се опитах да демонстрирам същността на скрипт, който създадох в R. Както може да се види от графиката, която се получава от този код, при едно от моите условия не имат стойност „Не“, за да завършите серията.

Казаха ми, че освен ако не мога да направя тази последна колона, която за съжаление няма допълнителни серии, толкова тънка, колкото колоните на друго място в графиката, няма да ми бъде разрешено да използвам тези графики. Това за съжаление е проблем, защото скриптът, който написах, произвежда стотици графики едновременно, пълни със статистика, индикатори за значимост, разпространени ленти за грешки и интелигентни корекции на оста y (тези функции, разбира се, не присъстват в MWE).

Малко други коментари:

  • Не е гарантирано, че тази колона за изключения е в края на графиката... така че ръчното настройване, за да се принуди серията да промени цвета и да се обърне редът, оставяйки допълнителното пространство от дясната страна, не е надеждно.

  • Опитах се да симулирам данните като константа 0, така че серията „да присъства“, но невидима, но както би се очаквало, редът на серията c(Не,Да) прави това пропускане на интервал, което също е неприемливо. Ето как беше отговорено на същия въпрос тук, но за съжаление не работи за мен с моите ограничения: Постоянна ширина за geom_bar в случай на липсващи данни и Включете място за липсващо ниво на фактор, използвано в естетиката на запълване в geom_boxplot

  • Опитах се да направя това и с фасети, но там възникнаха множество проблеми, включително прекъсвания на редове и грешки в анотациите, които добавям към оста x.

MWE:

library(ggplot2)

print("Program started")

x <- c("1","2","3","1","2","3","4")
s <- c("No","No","No","Yes","Yes","Yes","Yes")
y <- c(1,2,3,2,3,4,5)
df <- as.data.frame(cbind(x,s,y))

print(df)

gg <- ggplot(data = df, aes_string(x="x", y="y", weight="y", ymin=paste0("y"), ymax=paste0("y"), fill="s"));
dodge_str <- position_dodge(width = NULL, height = NULL);
gg <- gg + geom_bar(position=dodge_str, stat="identity", size=.3, colour = "black")

print(gg)

print("Program complete - a graph should be visible.")

person EngBIRD    schedule 06.03.2015    source източник
comment
@DavidRobinson Вярвам, че причината, поради която пропускането на пространство (естетически) не е валидна, се свежда до същата причина, поради която последователността на разстоянието по оста x спрямо последователността на ширината на колоната е невалидна. Всичко се свежда до естетическите предпочитания на моя шеф, които нямам сила да споря. Оценявам бързия ви коментар, но от гледна точка на стойността е възможна, това всъщност не е правилно твърдение поради естеството на факторите зад това състояние. От техническа настройка всъщност може да е невъзможно да се настрои това състояние без серията идентифициран стимулант.   -  person EngBIRD    schedule 06.03.2015
comment
Имате ли същия проблем, както е описан тук? Помага ли решението?   -  person tonytonov    schedule 06.03.2015
comment
@tonytonov Благодаря за отговора ви, но според второто куршум в моя списък с коментари, допълнителното пространство, което генерира този подход, е за съжаление по-лошо според мнението на моя шеф. Мисля, че голямата разлика в моя случай е, че нашите данни имат значително по-малко колони от тази публикация, така че допълнителното пространство е наистина ясно изразено.   -  person EngBIRD    schedule 06.03.2015
comment
А, съжалявам. Да, мога да потвърдя, че поръчката нарушава вашите данни, докато изглежда, че не би трябвало. В решението по-горе a липсва и мястото му е запазено, но тук No липсва и мястото му е изместено. Странно, не мога да кажа защо се случва това.   -  person tonytonov    schedule 06.03.2015


Отговори (2)


За сметка на това да направите свое собствено изчисление за x координатите на лентите, както е показано по-долу, можете да получите диаграма, която може да е близка до това, което търсите.

x <- c("1","2","3","1","2","3","4")
s <- c("No","No","No","Yes","Yes","Yes","Yes")
y <- c(1,2,3,2,3,4,5)
df <- data.frame(cbind(x,s,y) )
df$x_pos[order(df$x, df$s)] <- 1:nrow(df)
x_stats <- as.data.frame.table(table(df$x), responseName="x_counts")
x_stats$center <- tapply(df$x_pos, df$x, mean)
df <-  merge(df, x_stats, by.x="x", by.y="Var1", all=TRUE)
bar_width <- .7
df$pos <- apply(df, 1, function(x) {xpos=as.numeric(x[4]) 
                                if(x[5] == 1) xpos 
                                else ifelse(x[2]=="No", xpos + .5 -        bar_width/2, xpos - .5 + bar_width/2) } )
 print(df)
gg <- ggplot(data=df, aes(x=pos, y=y, fill=s ) )
gg <- gg + geom_bar(position="identity", stat="identity", size=.3,    colour="black", width=bar_width)
gg <- gg + scale_x_continuous(breaks=df$center,labels=df$x )
plot(gg)

----- редактиране -------------------------------------------- ------

Променено за поставяне на етикетите в центъра на лентите.

Дава следната диаграма

въведете описание на изображението тук

person WaltS    schedule 06.03.2015
comment
Чист отговор, може ли това да стане без дублиране на етикетите на оста x? - person EngBIRD; 06.03.2015
comment
Вашият код се нуждае от известно форматиране, за да се подобри четливостта му. Добре е, че OP получи своя отговор, но за следващите зрители по-чистото форматиране може да помогне и на други. - person Danny Bullis; 26.07.2021

Да, разбрах какво се е случило: трябва да внимавате факторите да бъдат фактори и числата да бъдат числа. В моя случай с stringsAsFactors = FALSE имам

str(df)
'data.frame':   7 obs. of  3 variables:
 $ x: chr  "1" "2" "3" "1" ...
 $ s: chr  "No" "No" "No" "Yes" ...
 $ y: chr  "1" "2" "3" "2" ...

dput(df)
structure(list(x = c("1", "2", "3", "1", "2", "3", "4"), s = c("No", 
"No", "No", "Yes", "Yes", "Yes", "Yes"), y = c("1", "2", "3", 
"2", "3", "4", "5")), .Names = c("x", "s", "y"), row.names = c(NA, 
-7L), class = "data.frame")

без фактори и числа, превърнати в знак поради cbind-ing (sic!). Нека имаме друг кадър с данни:

dff <- data.frame(x = factor(df$x), s = factor(df$s), y = as.numeric(df$y))

Добавяне на „фиктивен“ ред (ръчно за вашия пример, проверете версията expand.grid в свързания въпрос как да направите това автоматично):

dff <- rbind(dff, c(4, "No", NA))

График (премахнах допълнителните aes):

ggplot(data = df3, aes(x, y, fill=s)) + 
  geom_bar(position=dodge_str, stat="identity", size=.3, colour="black")

въведете описание на изображението тук

person tonytonov    schedule 06.03.2015
comment
Единствената причина, поради която имам числа в кавички на оста x, е, че бързах твърде много, за да публикувам въпроса, отколкото да разбера азбучните низове (и напълно пренебрегнати a, b, c и т.н.) Благодаря за отговора, аз научих нещо за факторите и cbind поради това, но докато не намеря начин да премахна това допълнително празно място, съм потънал. - person EngBIRD; 06.03.2015
comment
Правилно ли разбирам, че бихте искали да запазите ширината на четвъртата колона, както в моята графика по-горе, но подплатена вляво, по-близо до третата? Това няма ли да накара „4“ на скалата да стане по-близо до „3“ и да направи скалата неравномерна? - person tonytonov; 06.03.2015
comment
Да, абсолютно - тънък и подплатен. Тъй като моята графика в действителния ми скрипт няма линии на мрежата и пълни низове за етикети по оста x, моят шеф иска хомогенност за визуалния вид на лентите и интервалите, хомогенността на етикетите е по-малко важна. - person EngBIRD; 06.03.2015
comment
Виждам. Това е трудно, ще трябва да помисля малко. Вероятно включва известно хакване с scale_x_.... - person tonytonov; 06.03.2015
comment
Междувременно вижте донякъде подобен трик, който показвам тук. - person tonytonov; 06.03.2015
comment
Мисля, че ще използвам вашето решение тук - т.е. ще увелича интервала и ще добавя текстова анотация N.D. Така че, надявам се, че това не е твърде извън темата - ако е, ще отворя нов въпрос, но в случай, когато факторите не се използват изрично в кадъра с данни (и получавате разтягането спрямо разстоянието). Има ли начин да открия или принудя добавянето на това пространство? Моите данни се импортират в data.frame от sql import и подмножество, използващо [ ], а оста x на моя низ се третира с команда factor(x-axis) - person EngBIRD; 06.03.2015
comment
Трудно е да се каже набързо. Препоръчвам да зададете отделен въпрос, като свържете обратно тук. - person tonytonov; 06.03.2015