左手用R右手Python系列之——字符串格式化进阶

浏览: 1383

关于R语言字符串格式化之前无论是专题还是案例教程中均有所涉及,今日这一篇之所以重提是因为又找到了一个很好用的字符串格式化包。

这个包的语法源于Python风格,这样可以让那些从Python迁移过来的R语言学习者无需额外的记忆负担,即可平稳掌握R语言中的字符串格式化语法。

提到字符串格式化语法,我们一定能想到paste/pasteo函数,或者str_c函数,这两个函数的用法差不多,都是通过字符串与变量之间的拼接完成字符串格式化任务,但是问题是R语言中的字符处理并不想Python中那么灵活(仅靠“+”即可拼接字符),当一个字符串中需要插入多个变量时,拼接任务变得异常复杂。

好在R语言中保留了sprintf函数,这个源自C语言家族的字符串格式化函数,在左手用R右手Python系列推送文章中,曾经就这个问题专门写过一篇,但是这个sprintf函数使用起来并不是特别方便,特别是同类格式需要重复定义,同样的问题在Python的语法中也存在。

左右用R右手Python系列——字符串格式化输出

但是Python中有另外一套字符串格式化无法,使用format函数和{}来定义,最近发现R语言中的pystr包,也模仿着Python中的这一模式定义了一套风格一致的函数,所以现在在R语言中使用字符串格式化多了一个更加高效的途径。

项目主页:

#https://github.com/Ironholds/pystr
devtools::install_github("nicolewhite/pystr")

备注:(如果下载失败,可以尝试先将zip文件下载到本地,然后使用菜单式命令进行安装!)

library(pystr)

顺序参数:

sprintf("Hello %s, my name is %s.", "World", "RainDu")
#'Hello World, my name is RainDu.'
pystr_format("Hello {1}, my name is {2}.", "World", "RainDu")
#'Hello World, my name is RainDu.'

以上两句等价。

以上方法在Python中应该写成如下两种形式:

print("Hello %s, my name is %s." % ("World", "RainDu"))
#Hello World, my name is RainDu.
print("Hello {0}, my name is {1}.".format("World", "RainDu"))
#Hello World, my name is RainDu.

在设置顺序参数时,pystr_format函数的优越之处在于,它真正实现了右侧待插入字符参数的批量化,即如果右侧传入的字符串参数如果有多个,你可以直接传入命名的向量或者列表。

pystr_format("Hello {thing}, my name is {name}.", thing="World", name="RainDu")
pystr_format("Hello {thing}, my name is {name}.", c(thing="World", name="RainDu"))
pystr_format("Hello {thing}, my name is {name}.", list(thing="World", name="RainDu"))
#'Hello World, my name is RainDu.'

以上三句等价,风格与Python中str.format风格严格保持一致。

此时左侧的插入位置仅需输入右侧的对应名称即可,左侧顺序与右侧命名序列顺序无须严格一致(因为有名称可以索引)。

当然以上三句第一句看起来不是很友好,右侧参数是单个传入的,第二句第三个比较符合使用习惯。

那么命名关键字参数在Python中写法是这样的。

print("Hello {thing}, my name is {name}.".format(thing = "World",name = "RainDu"))
Hello World, my name is RainDu.
my_cars <- data.frame(car=rownames(mtcars), mtcars)
pystr_format("The {car} gets {mpg} mpg (hwy) despite having {cyl} cylinders.", my_cars)

image.png

image.png

借助R语言中函数强大的向量化功能,pystr_format函数可以很容易的实现批量化插入特定字符。

supers <- data.frame(
            first=c("Bruce", "Hal", "Clark", "Diana"),
            last=c("Wayne", "Jordan", "Kent", "Prince"),
            is=c("Batman", "Green Lantern", "Superman", "Wonder Woman")
            )
pystr_format("{first} {last} is really {is} but you shouldn't call them {first} in public.", supers)

image.png

而同样的功能要想在Python中实现,则要么借助循环,要么借助列表表达式或者高阶函数(结合lmanda表达式)。

supers = {
            "first":["Bruce", "Hal", "Clark", "Diana"],
            "last":["Wayne", "Jordan", "Kent", "Prince"],
            "the":["Batman", "Green Lantern", "Superman", "Wonder Woman"]
          }

使用普通的循环格式化:

strword = []
for first,last,the in zip(supers["first"],supers["last"],supers["the"]):
   print("{0:s} {1:s} is really {2:s} but you shouldn't call them {1:s} in public.".format(first,last,the))
   strword.append("{0:s} {1:s} is really {2:s} but you shouldn't call them {1:s} in public.".format(first,last,the))

Bruce Wayne is really Batman but you shouldn't call them Wayne in public.
Hal Jordan is really Green Lantern but you shouldn't call them Jordan in public.
Clark Kent is really Superman but you shouldn't call them Kent in public.
Diana Prince is really Wonder Woman but you shouldn't call them Prince in public.

使用列表表达式进行格式化:

supers["strword"] = ["{0:s} {1:s} is really {2:s} but you shouldn't call them {1:s} in public.".format(first,last,the) for first,last,the in zip(supers["first"],supers["last"],supers["the"])]

{'first': ['Bruce', 'Hal', 'Clark', 'Diana'],
'last': ['Wayne', 'Jordan', 'Kent', 'Prince'],
'strword': ["Bruce Wayne is really Batman but you shouldn't call them Wayne in public.",  "Hal Jordan is really Green Lantern but you shouldn't call them Jordan in public.",  "Clark Kent is really Superman but you shouldn't call them Kent in public.",  "Diana Prince is really Wonder Woman but you shouldn't call them Prince in public."], 'the': ['Batman', 'Green Lantern', 'Superman', 'Wonder Woman']}

使用高阶函数+匿名函数进行格式化

func = lambda x,y,z:"{0:s} {1:s} is really {2:s} but you shouldn't call them {0:s} in public.".format(x,y,z)
supers["strword2"] = list(map(func,supers["first"],supers["last"],supers["the"]))

image.png

以上便是在R语言中使用Python风格字符串格式化输出函数的主要内容,除此之外,pystr包内还内只有很多其他常见的字符串格式化函数,很多功能在stringr包内都能找到原型,这里仅以字符串格式化输出为例,其他的感兴趣可以自行了解,不再赘述。

image.png

推荐 0
本文由 杜雨 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册