Как на самом деле реализована опция BarSpacing в системе Mathematica?

Я пытаюсь реализовать функцию DateListBarChart, которая принимает датированные данные и выводит гистограмму с теми же местами размещения, что и DateListPlot. Важно, чтобы они отображали данные в одном и том же горизонтальном положении, если им предоставлены одни и те же данные, чтобы их можно было объединить с помощью Show. Мне трудно правильно настроить параметры BarSpacing, чтобы горизонтальный диапазон графика не менялся, а полосы оставались практически на одном и том же месте.

Мне не удалось вывести правильное масштабирование, так что BarSpacing->{0.2,0.3} приводит к тому, что 20% длины оси X, доступной для этой группы стержней, занимает расстояние между стержнями в этой группе, а 30 % - расстояние между группами стержней. По техническим причинам я делаю это, передавая вещи RectangleChart. Согласно документации, BarSpacing рассматривается как абсолютная величина в RectangleChart. Очевидно, что абсолютные размеры разрывов должны быть меньше, если серий больше, а столбцы должны быть уже.

Некоторые примеры:

arList = FoldList[0.9 #1 + #2 &, 0.01, RandomReal[NormalDistribution[0, 1], 24]]

{0.01, 0.334557, 2.02709, 1.1878, 1.9009, 3.08604, 2.36652, 3.04111, 
3.32364, 3.22662, 3.12626, 2.59118, 1.69334, 1.21069, 0.23171, 
0.689415, -0.852649, -0.124624, 0.58604, -0.481886, 0.221074, 
-0.300329, 2.36137, 0.427789, -1.47747}

dists = RandomChoice[{3, 4}, Length[arList]]
{4, 4, 4, 3, 4, 3, 4, 3, 4, 4, 3, 4, 4, 3, 4, 4, 4, 4, 3, 4, 3, 3, 3, 3, 3}

Результат:

RectangleChart[Transpose[{dists - 0 - 0/2, arList}], 
 PlotRange -> {{0, 100}, {-2, 4}}, ChartStyle -> EdgeForm[None], 
 Frame -> True, GridLines -> Automatic, BarSpacing -> {0, 0}]

введите здесь описание изображения

RectangleChart[Transpose[{dists - 0.7 - 0.5/2, arList}], 
 PlotRange -> {{0, 100}, {-2, 4}}, ChartStyle -> EdgeForm[None], 
 Frame -> True, GridLines -> Automatic, BarSpacing -> {0.7, 0.5}]

введите здесь описание изображения

Обратите внимание, что данные не охватывают то же расстояние по оси X, что и в предыдущем примере.

Это становится еще более запутанным, когда вы пытаетесь построить несколько серий (то же самое в этом примере, для иллюстрации).

RectangleChart[
 Transpose[{{dists - i/2 - j/2, arList}, {dists - i/2 - j/2, 
  arList}}, {2, 3, 1}], PlotRange -> {{0, 180}, {-2, 4}}, 
 ChartStyle -> EdgeForm[None], Frame -> True, Ticks -> None, 
  GridLines -> Automatic, BarSpacing -> {i, j}]

введите здесь описание изображения

Я целую вечность пытался найти правильную формулу, чтобы настройки BarSpacing для пользовательской функции (не показанной здесь) вызывали правильные интервалы и ширину полос, чтобы горизонтальный диапазон графика не менялся, как это делает BarSpacing.

Что мне не хватает?

РЕДАКТИРОВАТЬ: В ответ на belisarius, это пример того, куда я направляюсь. Это вроде как работает (столбцы не совсем совпадают с линией, но это, вероятно, даты, которые я использую), но случаи со сложенными столбцами не отображаются на графике со столбцами там, где они должны быть, как и любой вид гистограмма сама по себе, где есть несколько серий. (Я очень горжусь алгоритмом размещения метки даты: власть имущие не хотят отказываться от этого взгляда.)

введите здесь описание изображения

А вот один просто не работает. Данные должны заполнить горизонтальный диапазон. (Полосы разной ширины выбраны намеренно — это комбинация годовых и квартальных данных.)

введите здесь описание изображения

ИЗМЕНИТЬ 2

Я помню, почему я не использовал Filling в DateListPlot для рисования столбцов, как в пакете Майка Ханичерча - если у вас есть что-то кроме очень тонких столбцов, их верхний край окажется не в том месте.

DateListPlot[{dateARList}, 
 PlotStyle -> {AbsolutePointSize[6], Yellow}, Filling -> {1 -> 0}, 
 FillingStyle -> {1 -> {{AbsoluteThickness[12], Darker[Red, 0.25]}}}, 
 PlotRange -> All]

введите здесь описание изображения


person Verbeia    schedule 03.09.2011    source источник
comment
Я думаю, что функция VolumePlot Майка Ханичерча может оказаться полезной. Код можно найти здесь: library.wolfram.com/infocenter/MathSource/7526 Насколько я могу судить, этот код является предварительной версией новых графиков визуализации финансов в версии 8. Полезный?   -  person telefunkenvf14    schedule 03.09.2011
comment
Возможно пример (картинка) того, что вы пытаетесь сделать с DateListPlot (хотя и безуспешно), может помочь мне понять проблему...   -  person Dr. belisarius    schedule 04.09.2011
comment
@belisarius - посмотрите, поможет ли это. Стиль организационного графа очень специфичен.   -  person Verbeia    schedule 04.09.2011
comment
@Verbia, однажды у меня была очень похожая проблема с использованием Mathematica 7. Я решил ее, реализуя собственное поведение гистограммы по мере необходимости с использованием графических примитивов Rectangle []. С BarChart и связанными с ним графиками происходит слишком много волшебства, и в конце концов я отказался от него. После полдня работы у меня было решение в виде функции длиной в 100 строк.   -  person Gleno    schedule 04.09.2011
comment
@Gleno, это именно то, что я делаю, настраивая RectangleChart. Это больше похоже на 30 строк кода, чем на 100, но я все еще не могу найти правильную формулу для правильного расстояния между полосами относительно делений.   -  person Verbeia    schedule 04.09.2011
comment
@ telefunkenvf14 - см. мое редактирование - решение Майка работает только для тонких полос и вообще не работает для данных неправильной формы.   -  person Verbeia    schedule 04.09.2011


Ответы (2)


Возможно, используя параметр ChartElementFunction вместо BarSpacing помогает. Например, barplot в коде будет отображать столбчатую диаграмму таким образом, что каждый столбец имеет поля gapl слева и gapr справа, где gapl и gapr — доли общей ширины столбца.

scale[{{xmin_, xmax_}, {ymin_, ymax_}}, {gapl_, gapr_}] :=
 {{xmin (1 - gapl) + xmax gapl, ymin}, {xmax (1 - gapr) + xmin gapr, ymax}}

barplot[dists_, arList_, {gapl_, gapr_}, opts___] := 
 RectangleChart[Transpose[{dists, arList }], opts, 
  Frame -> True, 
  GridLines -> Automatic, BarSpacing -> 0,
  ChartElementFunction -> (Rectangle @@ scale[#, {gapl, gapr}] &)]

Использование:

Чтобы построить исходную гистограмму без пропусков

barplot[dists, arList, {0, 0}]

прямоугольная диаграмма без пропусков

Это приведет к построению гистограммы с полем 0,2 с обеих сторон, что приведет к гистограмме с зазорами в 0,4 раза больше общей ширины столбцов. Обратите внимание, что положение столбцов совпадает с положением на первом рисунке.

barplot[dists, arList, {0.2, 0.2}]

гистограмма с пробелами

Вы можете построить несколько серий, выполнив что-то вроде

Show[barplot[dists, arList 0.9, {0, 0.5}],
 barplot[dists, arList 0.8, {0.5, 0}, ChartStyle -> LightGreen]] 

две серии на одном сюжете

person Heike    schedule 04.09.2011
comment
+1 Круто, Хайке - я никогда не думал об ChartElementFunction. - person Verbeia; 04.09.2011
comment
Я только что подтвердил, что это работает. Оказывается, если вы масштабируете ширину прямоугольников по количеству серий (что я и так делал), вам даже не нужно использовать Show. Я беру значение параметра BarSpacing, а затем использую ChartElementFunction -> (Rectangle @@ barscale[#, {gapfactorwithin/(2 xscaling), gapfactorwithin/(2 xscaling)}] &), устанавливая BarSpacing обратно на 0 в фактическом RectangleChart. Еще раз спасибо Хайке, это очень мне помогло. Это еще один пример, когда надо перестать биться головой о клавиатуру и пораньше спрашивать в интернете :) - person Verbeia; 04.09.2011
comment
Жаль, что мы не можем взвесить наши голоса в соответствии с тем, сколько времени кто-то сэкономил нам :) - person Verbeia; 04.09.2011
comment
@Verbeia Bounties предназначены для вознаграждения за это - person Dr. belisarius; 04.09.2011
comment
хорошо, поэтому я просмотрел FAQ, и мне нужно подождать до завтра, чтобы установить это. - person Verbeia; 05.09.2011
comment
Я начал вознаграждение, равное разнице между моей репутацией и репутацией @Heike на момент ее открытия. Мне нужно подождать до завтра, пока я не присужу его. - person Verbeia; 06.09.2011
comment
Награжден. Еще раз спасибо, @Heike! - person Verbeia; 07.09.2011
comment
Спасибо, Вербея. Рад, что смог помочь. - person Heike; 07.09.2011
comment
@Verbeia, отличное спортивное мастерство в отношении вознаграждения за вознаграждение задним числом. Хайке, это прекрасное решение. - person Mr.Wizard; 18.10.2011

Вы можете снять жалобу на FillingStyle, воспользовавшись CapForm["Butt"].

list = {0.01, -0.81, 0.12, 0.81, 1.79, 1.1, 0.41, 1., 1.33, 1.08, 
  2.16, 1.13, 1.92, 1.64, 1.31, 1.94, 1.71, 0.91, 2.32, 0.95, 1.29, 
  1.28, 2.97, 4.45, 5.11}

DateListPlot[list, {2000, 8}, 
 PlotStyle -> {AbsolutePointSize[6], Yellow}, Filling -> {1 -> 0}, 
 FillingStyle -> {1 -> {{CapForm["Butt"], AbsoluteThickness[14], 
      Darker[Red, 0.25]}}}, PlotRange -> {0, 6}, ImageSize -> 400]

введите здесь описание изображения

person Mr.Wizard    schedule 17.10.2011
comment
это отличное решение! Он не подходит для сложенных столбцов и нескольких рядов, если я не выполняю некоторые манипуляции с наборами данных, чтобы они были кумулятивными. Но это может быть полезным вариантом для однолинейных гистограмм и гистограмм с учетом этой проблемы: have-pixelated-text-is-there" title="почему гистограмма, экспортированная из mathematica, имеет пиксельный текст"> stackoverflow.com/questions/7396898/ - person Verbeia; 18.10.2011
comment
@Verbeia, я знаю, что это не полное решение, но я подумал, что это будет полезно, и это очень просто. - person Mr.Wizard; 18.10.2011
comment
это так, и использование CapForm в опции Style малоизвестно. Этим +1 был я. - person Verbeia; 18.10.2011