學習Python不到一個月,雖然學的很渣,但是還是想通過這種途徑分享自己的學習心得,畢竟當初學習R語言也是這麼走過來的。
今天是R語言與Python綜合系列的第一篇,就聊一聊兩者在常用字符串輸出上的差異。
為了方便統一案例圖片的風格,今天統一在jupyter編輯器中編輯(R和Python)。
通常在R語言中我們使用最多的關於字符串輸出函數是paste和paste0。
這兩著之間的差別非常微小,如同其字面意思一樣,前者可以自定義字符串間隔符號,後者則默認沒有間隔符號。
paste和paste0都可以完成單個向量字符串的連接以及兩個向量間的匹配。
#生成10個隨機大寫字母作為案例:
myword<-sample(LETTERS,10,replace=FALSE)
我們可以列印出兩個函數的詳細參數表:
paste
function (..., sep = " ", collapse = NULL) #sep參數默認間隔為空格
.Internal(paste(list(...), sep, collapse))
paste0
function (..., collapse = NULL) #sep沒有間隔參數(無間隔)
.Internal(paste0(list(...), collapse))
單個向量的連接成字符串:
paste(myword,collapse="-")
'Q-C-X-B-M-I-E-P-G-V'
在拼接單個向量之時,通過設置collapse參數來控制字符之間的間隔符,最終輸出一個單值字符串。
paste0(myword,collapse="-")
'Q-C-X-B-M-I-E-P-G-V'
我們可以看到,在拼接單個向量為字符串的過程中,paste和paste0兩個函數並無太大區別,因為不涉及匹配參數sep。
通常情況下,我們使用paste和paste0做向量間的匹配情況比較多,這種情況多見於遍歷網頁,遍曆日期等。
比如假如我們們要遍歷一個網頁的網址如下:
隨機打開了網易雲課堂的一個課程欄目,看到一共有22頁課程,此時最簡單的遍歷網頁方法就是通過paste或者paste0。
http://study.163.com/category/400000000146050#/
url<-"http://study.163.com/category/400000000146050#/?p="
num<-1:22
myurl<-paste(url,num,sep="");myurl
myurl<-paste0(url,num);myurl
對比兩個函數的用法,大家應該能領會其中的差別了吧,paste0把paste的sep參數簡化了,直接強制設定為無間隔,此時做向量間匹配的話,paste0函數就可以不用設置sep參數,而paste則需設置,當然雖然在遍歷網頁時確實節省代碼,但也不是任何場合都是如此。
比如我要拼接時間與日期,而且要求以「-」間隔,此時你還是需要使用傳統的paste函數來完成這個任務,因為paste0已經不存在sep參數了。
mydate<-paste(2001:2005,"06",sep="-");mydate
還有一個stringr包中字符串拼接函數str_sub()也可以高效的完成上述工作,但是因為需要額外加載包,所以平時我用的頻率不高。
library(stringr)
str_c(myword,collapse ="")
str_c(url,num,sep = "")
在R語言中,字符串格式化輸出除了以上常見操作之外,還有一些非常重要的需求,比如格式化輸出百分比,格式化輸出日期時間等。
以百分比為例:
我們可以通過一些擴展包內提供的百分比構造函數來高效的完成百分比構造過程。
library(sca)
library(dplyr)
percent(seq(0,0.1,0.01),d=2,sep="") #其中的參數控制百分比輸出的小數點後位數。
library(scales)
percent(runif(10,0,1)) #percent函數說明了目前沒法看到如何控制小數點顯式位數。
接下來跟大家介紹一個重量級的函數——sprintf。此函數據說來頭不小。(據說繼承自C/C++),該函數的使用可以大大簡化字符串格式化輸出的操作流程。
%d 整數 %02d d代表整數;2代表長度;0代表不足長度用0補齊
%f 浮點數 %4.2f 第一個數字代表總位數;第二個數字代表小數點位數
%s 字符串
%% 百分比
該函數的參數遠不止這三個,太多我也記不住,而且平時使用頻率最高的也就這三個,所以秉著投入回報率最高的原則,建議大家用什麼記什麼。
所以以上百分比過程便只剩下這麼幾個代碼:
sprintf("%d%%",1:10) #遍歷百分比
sprintf("%d-%d-%02d",2001,12,1:30) #遍曆日期:
sprintf("有%.1f%%的人評價變形金剛5較差",30.7)
'有30.7%的人評價變形金剛5較差'
sprintf("%s是阿里巴巴的%s","馬雲","老闆")
'馬雲是阿里巴巴的老闆'
當然,以上過程完全可以通過paste和str_c函數完成,只是sprintf函數來寫這些東西看起來更優化,更有逼格。
好了重於輪到Python了,對於一個小菜鳥來說,第一次寫Pyhon的教程心情很忐忑,注意了下面要換編輯器了(雖然仍然使用的jupter裡)。
Pyhton:
Pyhton中的字符串格式化輸出大概有兩套比較完善的系統(我所知的)。
其實第一套系統應該也是源於C/C++(感覺跟R裡面的格式化符號規則是一致的)
print("I'm %s. I'm %d year old" % ('raindu',26))
以上使用print函數輸出了寶寶的大名和芳齡~_~,python中的字符串格式符規則是,在要輸出的主句中對應位置插入格式符,在句尾之後使用 % 連接一個元組,元組內提供主句所有的待格式化的字符串,有幾個需要格式化的字符串就需要在元組中提供幾個字符串對象,而且順序一定要與待格式化的字符串在主句的位置一一對應。
另一種方式可以使用字典進行字符傳遞。
print("I'm %(name)s. I'm %(age)d year old" % {'age':26,'name':'raindu'})
這種方式最大的好處就是,以命名參數的形式傳入,這樣可以不用考慮字典內的鍵值對順序。(因為有名字可以索引)
Python中的字符串格式化符號相對於R規定的更加嚴格、細緻,上述所述R中的字符串:%s、數值%d、浮點型%f是通用的。
除此之外,格式化符號內部還可以提供更為詳盡的格式控制。
%[(name)][flags][width].[precision]typecode
(name)為名稱
flags可以有+,-,' '或0。+表示右對齊。-表示左對齊。' '為一個空格,表示在正數的左側填充一個空格,從而與負數對齊。0表示使用0填充。
width表示顯示寬度
precision表示小數點後精度
但是發現網上關於Python教程中,使用最多的還是.format這種字符串輸出形式。
format 函數:
'{2},{1},{0}'.format("小偉","大偉","小三")
'小三,大偉,小偉'
'{1}和{0}是一對{2}'.format("大偉","小偉","基友")
'小偉和大偉是一對基友'
這種傳參的方式可以看做是位置參數(順序),即在要輸出的主句中插入末尾提供的對應字符串位置,即可完成格式化過程。
如果你不想在主句對應的花括號內寫位置參數,你必須保證末尾提供的字符串順序與主句對應要插入的位置保持一致。
'{}和{}是一對好{}'.format("大偉","小偉","基友")
當然,你也可以在format括號內內對字符串進行命名,然後將對應名字傳入主句對應花括號內部。
"I'm {name}. I'm {age} year old".format(age=26,name='raindu')
這種情況下你也不必考慮format括號內的字符串對應順序,因為所有的字符串都有名稱,只傳入名稱,函數即可自動完成索引配對。
使用以上兩種方式都可以方便的遍歷網頁:
url="http://study.163.com/category/400000000146050#/?p="
myurl1=[]
for i in range(1,23):
urlm=url+'%d' % i
myurl1.append(urlm)
print(urlm)
myurl1=[]
for i in range(1,23):
urlm=url+'{}'.format(i)
myurl1.append(urlm)
print(urlm)
好了今天就這樣了,要同時貫穿兩門語言真的不是一件容易的事情,長路漫漫以後日子要苦逼了。
總結一下:
R語言字符串格式化輸出:
paste/paste0
stringr::str_c
sca::percent
scales::percent
sprintf
Python字符串格式化輸出:
關於傳參的規則:
使用格式化符號可以通過位置參數【比較好用】、命名參數來實現字符串格式化輸出【使用字典反而繁瑣了】。
使用.format格式化輸出可以通過順序參數(編號順序)、位置參數(前後位置順序需一致)、名稱參數(比較自由不用考慮順序)