48

语言: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)

在此处输入图像描述

我想|排队。他们现在没有;很公平,我没有将列填充到相同的宽度。所以我使用format让每一列的宽度相同(稍后我将编写代码来自动确定每列的宽度,但现在让我们忽略它):

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

在此处输入图像描述

看看它仍然不稳定吗?然而,如果我看df.padded,我得到:

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

所以每个单元格肯定被填充到相同的长度。

造成这种情况的原因可能是因为它的默认字体(无论如何在我的系统上,Linux)不是固定宽度。

所以我的问题是: 我可以为函数指定固定宽度的字体吗?menu(..,graphics=T)

更新

@RichieCotton 注意到,如果你用它看menugraphics=Tselect.list会调用tcltk::tk_select.list.

所以看起来我必须为此修改tcltk选项。来自@jverzani:

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

在此处输入图像描述

鉴于menu(...,graphics=T)调用tcltk::tk_select.listwhengraphics为 TRUE,我的猜测是这是一个可行的选择,因为任何能够menu首先显示图形的发行版也将具有tcltk它,因为它需要调用tk_select.list.

(顺便说一句,我在文档中找不到任何可以提示我尝试的内容tcl('option','add',...),更不用说调用了该选项*Listbox.font!)

另一个更新——仔细查看了select.listmenu代码,结果在 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),这肯定会起作用。

谢谢大家。

4

2 回答 2

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

于 2012-06-12T22:00:32.880 回答
0

我不明白你为什么不想使用 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) 中字符数的最大长度。您可以根据您的数据更改它以反映它。

于 2012-05-08T03:57:51.720 回答