График временной шкалы в стиле Ганта (в базе R)

У меня есть датафрейм, который выглядит так:

       person n start end
1         sam 6     0   6
2        greg 5     6  11
3     teacher 4    11  15
4         sam 4    15  19
5        greg 5    19  24
6       sally 5    24  29
7        greg 4    29  33
8         sam 3    33  36
9       sally 5    36  41
10 researcher 6    41  47
11       greg 6    47  53

Где начало и конец - это время или продолжительность (sam говорил от 0 до 6; greg от 6 до 11 и т. Д.). n - как долго (в данном случае # слов) человек говорил. Я хочу представить это как временную шкалу в базе R (в конечном итоге я могу задать аналогичный вопрос, используя ggplot2, но этот ответ специфичен для базы R [когда я говорю «база», я имею в виду пакеты, которые поставляются со стандартной установкой]).

Ось у будет человеком, а ось х будет временем. Надеемся, что конечный продукт будет выглядеть примерно так для данных выше:

Я хотел бы использовать базу R, чтобы сделать это. Я не уверен, как подойти к этому. Мои мысли состоят в том, чтобы использовать точечный график и построить точечный график, но не использовать точки. Тогда идите через это с квадратными сегментами конца. Я не уверен в том, как это будет работать, поскольку сегментам нужны числовые точки x и y, чтобы сделать сегменты, а ось y является категориальной. Другая идея состоит в том, чтобы преобразовать коэффициенты в числовые (назначить каждому фактору число) и построить в виде пустой диаграммы рассеяния, а затем перейти к квадратным отрезкам конечных линий. Это может быть мощным инструментом в моей области, глядя на образцы речи.

Заранее благодарю за помощь.

PS аргумент для прямоугольных отрезков segments(... , lend=2) чтобы сэкономить время на поиске этой информации для тех, кто не знаком со всеми аргументами сегмента.

Ответы на вопрос(3)

что хотите решение Base R, но не говорите почему. Так как это одна строка кода вggplotЯ все равно покажу это.

library(ggplot2)
ggplot(dat, aes(colour=person)) + 
    geom_segment(aes(x=start, xend=end, y=person, yend=person), size=3) +
    xlab("Duration")

 Tyler Rinker26 мар. 2012 г., 08:51
@Andrie Спасибо, это мой первый пакет для общего потребительского использования (я уже создал 2 пакета для себя, но я стараюсь как можно более дисциплинированно для первого таймера) и хочу обеспечить максимально возможное качество продукта. Спасибо за зависимости против предлагает информация +1
 Andrie26 мар. 2012 г., 08:46
@TylerRinker Хороший. У вас есть два варианта, чтобы включить это в пакет без введения зависимости. 1) Используйтеdontrun блокcran.r-project.org/doc/manuals/... 2) Использованиеsuggests(ggplot2) в вашей упаковкеDESCRIPTION а потомrequire(ggplot2) в вашем примере. Таким образом,ggplot2 Пакет загружается, только если пользователь действительно хочет его использовать.
 Tyler Rinker25 мар. 2012 г., 21:01
@ Андри, это очень мило. Причина, по которой я не хочу использовать ggplot, заключается в том, что в качестве примечаний Чейза я избегаю всех зависимостей, кроме wordcloud (так как этот пакет выполняет некоторое кодирование на C, я не в состоянии это сделать). При этом функция будет отображать график, но также будет возвращать обработанный фрейм данных, который может быть передан в ggplot (я планирую показать это в качестве примера в моем пакете, хотя, возможно, придется использовать# чтобы получить код для прохождения тестов на создание пакета. Причина, по которой я заинтересован в ggplot, заключается в том, что я буду использовать одну и ту же идею для повторных измерений, и здесь будет неплохо использовать огранку. Отличная работа, Андри. +1
 John25 мар. 2012 г., 20:41
Он также может захотеть больше контролировать внешний вид, лучше понимать базовую графику, интегрировать ее с другими базовыми графическими графиками или просто иметь предпочтения. О, и это на самом деле не одна строка. У вас там как минимум 2 строки, которые легко интерпретируются как 3, и вы забыли install.packages ('ggplot2').
 Chase25 мар. 2012 г., 20:31
Похоже, он избежал всех других внешних зависимостей для пакета, который он разрабатывает, и пытается сохранить его таким образом:stackoverflow.com/questions/9857787/....

но так как я сделал это, я опубликую это :)

Вот общая функция для построения диаграммы Ганта (без зависимостей):

plotGantt <- function(data, res.col='resources', 
                      start.col='start', end.col='end', res.colors=rainbow(30))
{
  #slightly enlarge Y axis margin to make space for labels
  op <- par('mar')
  par(mar = op + c(0,1.2,0,0)) 

  minval <- min(data[,start.col],na.rm=T)
  maxval <- max(data[,end.col],na.rm=T)

  res.colors <- rev(res.colors)
  resources <- sort(unique(data[,res.col]),decreasing=T)

  plot(c(minval,maxval),
       c(0.5,length(resources)+0.5),
       type='n', xlab='Duration',ylab=NA,yaxt='n' )
  axis(side=2,at=1:length(resources),labels=resources,las=1)
  for(i in 1:length(resources))
  {
    yTop <- i+0.1
    yBottom <- i-0.1
    subset <- data[data[,res.col] == resources[i],]
    for(r in 1:nrow(subset))
    {
      color <- res.colors[((i-1)%%length(res.colors))+1]
      start <- subset[r,start.col]
      end <- subset[r,end.col]
      rect(start,yBottom,end,yTop,col=color)
    }
  }
  par(mar=op) # reset the plotting margins
}

Пример использования:

data <- read.table(text=
'"person","n","start","end"
"sam",6,0,6
"greg",5,6,11
"teacher",4,11,15
"sam",4,15,19
"greg",5,19,24
"sally",5,24,29
"greg",4,29,33
"sam",3,33,36
"sally",5,36,41
"researcher",6,41,47
"greg",6,47,53',sep=',',header=T)

plotGantt(data, res.col='person',start.col='start',end.col='end',
          res.colors=c('green','blue','brown','red','yellow'))

Результат:

 digEmAll25 мар. 2012 г., 23:10
@TylerRinker: Всегда пожалуйста :). Однако я немного изменил код, чтобы освободить место для меток.
 Tyler Rinker25 мар. 2012 г., 21:22
Также спасибо за слово Гантта. Я не знал, как это называется.
 Tyler Rinker25 мар. 2012 г., 21:20
Этот ответ также соответствует параметрам, которые я перечислил. Это выглядит потрясающе. Спасибо, что поделились, немного другой подход. +1
 Tyler Rinker09 сент. 2012 г., 00:21
Я хочу включить некоторые из этих работ в пакет. Я хочу правильно процитировать вас. Можете ли вы связаться со мной @ [email protected]
 digEmAll10 сент. 2012 г., 09:13
@TylerRinker: спасибо, но мне не нужно ссылаться на этот маленький кусочек кода. Не стесняйтесь использовать его;)
Решение Вопроса

все, что вам нужно сделать, это назначить номера категориям (1: 5) и отслеживать их. Использование по умолчанию as.numeric () фактора обычно нумерует их в алфавитном порядке, но вы все равно должны это проверить. Создайте свой график с аргументом xaxt = 'n'. Затем используйте команду axis (), чтобы вставить ось Y.

axis(2, 1:5, myLabels)

Имейте в виду, что всякий раз, когда вы планируете, единственный способ разместить вещи - это число. Категориальными значениями x или y всегда являются только числа 1: nКатегории с метками названий категорий вместо чисел на оси.

Что-то вроде следующего достаточно близко (если предположить, что ваш объект data.frame называется datf) ...

datf$pNum <- as.numeric(datf$person)
plot(datf$pNum, xlim = c(0, 53), type = 'n', yaxt = 'n', xlab ='Duration (words)', ylab = 'person', main = 'Speech Duration')
axis(2, 1:5, sort(unique(datf$person)), las = 2, cex.axis = 0.75)
with(datf, segments(start, pNum, end, pNum, lwd = 3, lend=2))
 John25 мар. 2012 г., 23:07
без проблем... :).-
 Tyler Rinker25 мар. 2012 г., 21:05
очень хорошо. Это довольно близко к тому, что я просил (в пределах базового параметра), и я могу взять это отсюда. Очень хорошая работа.
 Roman Luštrik30 апр. 2012 г., 20:46
Хотите добавить изображение результата?
 Tyler Rinker25 мар. 2012 г., 21:07
Надеюсь, ты не возражаешь, но я поскользнулся, lend=2 в вашsegments использовать.

Ваш ответ на вопрос