R中是否有类似于Python的%字符串格式化操作符?

61

我有一个需要使用日期变量发送请求的网址。这个https地址接受日期变量。我想使用类似于Python中格式化运算符%的东西将日期分配给地址字符串。R是否具有类似的运算符,或者我需要依赖paste()函数?

# Example variables
year = "2008"
mnth = "1"
day = "31"

这是我在Python 2.7中会做的事情:

url = "https:.../KBOS/%s/%s/%s/DailyHistory.html" % (year, mnth, day)

或者在Python 3+中使用.format()。

我所知道的在R中的唯一方法似乎很冗长,并且依赖于paste:

url_start = "https:.../KBOS/"
url_end = "/DailyHistory.html"
paste(url_start, year, "/", mnth, "/", day, url_end) 

有没有更好的做法?


1
也许可以这样写:paste(url_start, paste(year,mnth,day,sep="/"), url_end) - CPak
请参见 https://dev59.com/6WQm5IYBdhLWcg3wnACR#17476306,该链接涉及sprintf格式字符串按名称引用的问题。 - G. Grothendieck
3个回答

77

R语言中对应的函数是sprintf

year = "2008"
mnth = "1"
day = "31"
url = sprintf("https:.../KBOS/%s/%s/%s/DailyHistory.html", year, mnth, day)
#[1] "https:.../KBOS/2008/1/31/DailyHistory.html"

另外,虽然我认为这有点过度,但你也可以自己定义运算符。

`%--%` <- function(x, y) {

  do.call(sprintf, c(list(x), y))

}

"https:.../KBOS/%s/%s/%s/DailyHistory.html" %--% c(year, mnth, day)
#[1] "https:.../KBOS/2008/1/31/DailyHistory.html"

3
或许也值得展示一个例子来说明向量化,例如 "https:.../KBOS/%s/%s/%s/DailyHistory.html" %--% list(1999:2000, mnth, day) 或其等效的sprintf函数。(我猜在Python中,他们会使用循环来完成这种操作。) Translated: 也许值得展示一个例子来说明向量化,比如像这样的 "https:.../KBOS/%s/%s/%s/DailyHistory.html" %--% list(1999:2000, mnth, day) 或相当于 sprintf 的函数。(我想在 Python 中他们可能会用循环完成这种操作。) - Frank
当你的文本中有其他百分号字符时,情况就变得棘手了...例如带通配符运算符的SQL查询。 - John F

45
作为 sprintf 的替代方案,你可能想要尝试一下 glue
更新:在 stringr 1.2.0 中,他们添加了一个 glue::glue() 的包装函数,str_glue()


library(glue)

year = "2008"
mnth = "1"
day = "31"
url = glue("https:.../KBOS/{year}/{mnth}/{day}/DailyHistory.html")

url

#> https:.../KBOS/2008/1/31/DailyHistory.html

11

stringr 包有一个 str_interp() 函数:

year = "2008"
mnth = "1"
day = "31"
stringr::str_interp("https:.../KBOS/${year}/${mnth}/${day}/DailyHistory.html")
[1] "https:.../KBOS/2008/1/31/DailyHistory.html"
或者使用列表(注意现在传递的是数字值):

stringr::str_interp("https:.../KBOS/${year}/${mnth}/${day}/DailyHistory.html", 
                            list(year = 2008, mnth = 1, day = 31))
[1] "https:.../KBOS/2008/1/31/DailyHistory.html"
顺便提一下,格式化指令也可以传递,例如,如果月份字段需要两个字符宽度:


stringr::str_interp("https:.../KBOS/${year}/$[02i]{mnth}/${day}/DailyHistory.html", 
                    list(year = 2008, mnth = 1, day = 31))
[1] "https:.../KBOS/2008/01/31/DailyHistory.html"

这是 Python 中最接近灵活的 format。看起来非常不错。 - MichaelChirico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接