Укажите моноширинный шрифт в `menu` - PullRequest
48 голосов
/ 08 февраля 2012

Язык: R. Вопрос: Можно ли указать шрифт фиксированной ширины для функции menu(..,graphics=T)?

Пояснение:

Я недавно задал этот вопрос о том, как заставить пользователя интерактивно выбирать строку фрейма данных:

df <- data.frame(a=c(9,10),b=c('hello','bananas'))
df.text <- apply( df, 1, paste, collapse=" | " )
menu(df.text,graphics=T)

enter image description here

Я бы хотел, чтобы | выстроился в линию. Они не в данный момент; честно говоря, я не разложил колонки на одинаковую ширину. Поэтому я использую format, чтобы получить для каждого столбца одинаковую ширину (позже я напишу код для автоматического определения ширины столбца, но пока проигнорируем это):

df.padded <- apply(df,2,format,width=8)
df.padded.text <- apply( df.padded, 1, paste, collapse=" | ")
menu( df.padded.text,graphics=T )

enter image description here

Видишь, как все еще шатко Тем не менее, если я посмотрю на df.padded, я получу:

> df.padded
     a            b           
[1,] " 9        " "hello     "
[2,] "10        " "bananas   "

Таким образом, каждая ячейка определенно имеет одинаковую длину.

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

Итак, мой вопрос: Можно ли указать шрифт фиксированной ширины для функции menu(..,graphics=T)?

Обновление

@ RichieCotton заметил, что если вы посмотрите на menu с graphics=T, то он вызовет select.list, что, в свою очередь, вызовет tcltk::tk_select.list.

Похоже, мне придется изменить для этого опции tcltk. От @jverzani:

library(tcltk)
tcl("option", "add", "*Listbox.font", "courier 10")
menu(df.padded.text,graphics=T)

enter image description here

Учитывая, что menu(...,graphics=T) вызывает tcltk::tk_select.list, когда graphics - ИСТИНА, я предполагаю, что это жизнеспособный вариант, так как любой дистрибутив, который мог бы отображать графическое menu в первую очередь, также имел бы tcltk на нем, так как ему нужно позвонить tk_select.list.

(Кроме того, я не могу найти в документации ничего, что дало бы мне подсказку попробовать tcl('option','add',...), не говоря уже о том, что опция называлась *Listbox.font!)

Еще одно обновление - более внимательно посмотрел на код select.list и menu, и оказалось, что в Windows (или, если .Platform$GUI=='AQUA' - это Mac?), tcltk::tk_select.list вообще не вызывается, а просто внутренний код. Поэтому изменение * Listbox.font не повлияет на это.

Полагаю, я просто:

  • если tcltk есть, загрузите его, установите * Listbox.font на courier и используйте tcltk::tk_select.list явно
  • если его там нет, попробуйте menu(...,graphics=T) хотя бы получить графический интерфейс (который не будет моноширинным, но лучше, чем ничего)
  • , если это тоже не удастся, то просто вернитесь к menu(...,graphics=F), что точно сработает.

Спасибо всем.

Ответы [ 2 ]

1 голос
/ 13 июня 2012

Еще один подход к заполнению:

na.pad <- function(x,len){
    x[1:len]
}

makePaddedDataFrame <- function(l,...){
    maxlen <- max(sapply(l,length))
    data.frame(lapply(l,na.pad,len=maxlen),...)
}

x = c(rep("one",2))
y = c(rep("two",10))
z = c(rep("three",5))

makePaddedDataFrame(list(x=x,y=y,z=z))

Функция na.pad() использует тот факт, что R автоматически дополнит вектор NA, если вы попытаетесь проиндексировать несуществующие элементы.

makePaddedDataFrame() просто находит самый длинный и дополняет остальные до соответствующей длины.

0 голосов
/ 08 мая 2012

Я не понимаю, почему вы не хотите использовать View (df) (получите rowid, поместите содержимое во временный фрейм данных и отобразите его с помощью команды View)

Редактировать: ну, просто используйте sprintf команду

Создать функцию f для извлечения строк из объекта фрейма данных

f <- function(x,sep1) {
 sep1=format(sep1,width=8)
 xa<-gsub(" ","",as.character(x[1]))
 a1 <- nchar(xa)
 xa=format(xa,width=8)
 xb=gsub(" ","",as.character(x[2]))
 b1 <- nchar(xb)
 xb=format(xb,width=8)
 format1=paste("%-",10-a1,"s%s%-",20-b1,"s",sep="")
 concat=sprintf(format1,xa,sep1,xb)
 concat
 }

df <- data.frame(a=c(9,10),b=c('hello','bananas'))

df.text <- apply( df, 1, f,sep1="|")

menu(df.text,graphics=T)

Конечно, ограничения, используемые в sprintf 10, 20, представляют собой максимальную длину для количества символов в столбце фрейма данных (a, b). Вы можете изменить это, чтобы отразить это согласно вашим данным.

...