Управляйте шириной столбца на графике 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
Ваш код нуждается в некотором форматировании, чтобы улучшить его читабельность. Хорошо, что ОП получил свой ответ, но для последующих зрителей более чистое форматирование может помочь и другим. - 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
Думаю, я воспользуюсь вашим решением здесь, т.е. заставлю пробел и добавлю текстовую аннотацию ND Итак, я надеюсь, что это не слишком не по теме - если это так, я открою новый вопрос, но в случае, когда факторы явно не используются во фрейме данных (и вы получаете растяжение против интервала). Есть ли способ обнаружить или принудительно добавить это пространство? Мои данные импортируются в data.frame из импорта sql, а подмножество с использованием [ ] и моя ось строки x обрабатывается с помощью команды factor(x-axis) - person EngBIRD; 06.03.2015
comment
Трудно сказать навскидку. Рекомендую задать отдельный вопрос, дав ссылку сюда. - person tonytonov; 06.03.2015