在`menu`中指定monospace字体

时间:2012-02-08 07:16:49

标签: r fixed-width monospace

语言:R。问题:我可以为menu(..,graphics=T)函数指定固定宽度字体吗?

说明:

我最近询问this question如何让用户以交互方式选择一行数据框:

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)为TRUE时tcltk::tk_select.list调用graphics,我的猜测是这是一个可行的选项,因为任何能够显示图形的发行版{{1}首先,它还会有menu,因为它需要调用tcltk

(顺便说一下,我在文档中找不到任何可以提示tk_select.list的提示,更不用说选项被称为tcl('option','add',...)了!)

另一次更新 - 仔细查看了*Listbox.fontselect.list代码,结果发现在Windows上(或menu - 是Mac?),.Platform$GUI=='AQUA'根本没有被调用,而只是一些内部代码。因此修改'* Listbox.font'不会影响这一点。

我想我只是:

  • 如果有tcltk,请加载它,将* Listbox.font设置为courier,并明确使用tcltk::tk_select.list
  • 如果不存在,请尝试tcltk::tk_select.list至少获得一个图形界面(不是等宽的,但总比没有好)
  • 如果失败,那么只需回退到menu(...,graphics=T),这肯定会有用。

谢谢大家。

2 个答案:

答案 0 :(得分: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()只找到最长的一个并将其余部分填充到匹配的长度。

答案 1 :(得分:0)

我不明白为什么你不想使用View(df)(获取rowid,将内容放入temp.data帧并使用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)中字符数的最大长度。您可以根据数据进行更改以反映它。