Укажите моноширинный шрифт в `menu`
Язык: 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)
?
Update
@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
TRUE, я предполагаю, что это жизнеспособный вариант, так как любой дистрибутив, который мог бы отображать графический 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 в курьер и используйте
tcltk::tk_select.list
явно
- если его нет, попробуйте
menu(...,graphics=T)
, чтобы хотя бы получить графический интерфейс (который не будет моноширинным, но лучше, чем ничего).
- если это тоже не сработает, тогда просто вернитесь к
menu(...,graphics=F)
, который определенно будет работать.
Спасибо всем.
Ответы
Ответ 1
Другой подход к заполнению:
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()
просто находит самый длинный и подставляет остальную часть до соответствующей длины.
Ответ 2
Я не понимаю, почему вы не хотите использовать View (df) (получите rowid, поместите содержимое в фрейм данных temp. и покажите его с помощью команды 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). Вы можете изменить его, чтобы отразить его в соответствии с вашими данными.