Подтвердить что ты не робот

Укажите моноширинный шрифт в `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), который определенно будет работать.

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

4b9b3361

Ответ 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). Вы можете изменить его, чтобы отразить его в соответствии с вашими данными.