工作中常常需要重复式的数据处理过程,如果写成循环执行的脚本就会方便很多。在编写这样的脚本时,有时会遇到变量名称和字符串的转换问题。在R中,这两个问题要使用assign()和get()函数解决。
get():返回与字符串同名的变量的值
assign():为字符串变量的字符串赋值
这两个函数有什么实际用处呢?假如我们有100个数据文件,名称类似1.txt,2.txt,...,100.txt。现在需要把这100个文件的数据分别读取:
> n = 100
> suffix = "txt"
> vari = "data"
> for(i in n) {
+ file_name = paste(i, suffix, sep = ".")
+ x_name = paste(vari, i, sep = "_")
+ assign(x_name, read.table(file_name))
+ }
这样就会生成data_1到data_100共100个变量,分别读取了100份数据。assign的作用就是一个中介,因为我们希望把变量的名称都按一个规律命名,用到了循环和字符串的拼接。但这个名称只是字符串,assign就把字符串变成了变量,付给它所要的值。而如果我们想分别看看这100个变量的长度:
> for (i in 1:n) {
+ y_name = paste(vari, i, sep = "_")
+ print(length(get(y_name)))
+ }
get()就像assign()的逆过程,因为我们希望依次得到这些有规律的变量,就把变量的名称拼接成字符串,赋值给了临时变量y_name。我们实际的目的是处理y_name这个字符串所代表的变量,因此使用get()函数获得。
R中这两个函数,通过名字就能理解其作用了,get就是获取,assign就是分配,对应其作用还是很好记的。而Python中的类似方法,就不太好记了。
eval():将字符串当成有效Python表达式来求值,并返回计算结果
exec():将字符串当成有效的Python语句来执行,不返回计算结果
在处理字符串和变量转换的时候,eval()的用法和get()一样,而exec()和assign()稍有不同。因为Python中的这两个函数,原理不一样,本身能够处理其他问题。
例如,print(“1+1”)输出的还是1+1,而print(eval("1+1"))则会输出计算结果2。在本篇讨论的应用场景,eval()可以和R中的get()一样,如果 b = 1 而 a = "b",那么eval(a)则会返回b的值1。
exec()的使用则和assign()不同,因为其功能本质是将一段字符串当作Python语句来执行。如果要达到同样的效果,需要先写一个字符串的赋值语句,然后用exec()执行。例如,a = "data_1 = pd.read_csv('file_1.csv')",那么exec(a)就会执行双引号中间的语句,读取文件数据并赋值给data_1。如果想完成第一个例子的批量读取文件,写入循环中会比R略多几行,这里就不给出我的代码示例了。
其中Python中还有其他函数可以达到类似的效果,在网上搜索的时候就找到过比如locals()和vars(),本篇并没有继续深入研究。另外,eval()可以当作evaluate的缩写,exec()是execute的缩写,在其他编程语言中都有这两个函数,作用是一样的。维基百科可以搜索到一些介绍,这两个函数的本质很强大,不过本人暂时没有搞清楚,后续如果找到更多的资料,再专门介绍这两个函数。
函数小结
R Python
get() eval()
assign() exec()