2020-013 R包不裝也能用

R包不裝也能用

因為功能比較高級的R包都會依賴很多包垄潮,依賴包又會依賴其他包,所以裝包是個麻煩的事。

之前那個包怕磨,不管從GitHub裝還是本地裝,裝的時候老是出現(xiàn)各種亂七八糟的錯誤消约。

但是我又不是需要你R包里的全部函數(shù)肠鲫,有些我不用的函數(shù)還要因為它裝很多其他的包或者導(dǎo)致安裝失敗就很氣。

反正R包里有源碼或粮,不如直接運行源碼吧导饲!


下載zip,然后解壓。

函數(shù)都編寫在revolver-masterR文件夾內(nèi)的各個文件中渣锦。

新建一個環(huán)境硝岗,來存儲函數(shù)。

base_dir = "../revolver-master/R"
files = list.files(base_dir)
revolver = new.env() 
for (file in files) {
  source(paste(base_dir,file,sep='/'),local=revolver)   #在revolver環(huán)境中運行這些代碼
}

之后就可以通過revolver$引用這些函數(shù)了袋毙,和安裝包后的revolver::不同型檀。

image-20200812194321445

安裝好的包可以library導(dǎo)入,暴露出函數(shù)娄猫。那這個呢贱除?

可以用attachdetach媳溺。

attach(revolver)
CCF()
detach(revolver)

雖然這些函數(shù)已經(jīng)存儲了月幌,但是由于我們不是正常安裝的包,所以函數(shù)在使用到其他未安裝包的時候就會有運行錯誤悬蔽。

那我就想檢查一下我source的每個文件都導(dǎo)入或使用了哪些依賴包扯躺。

用一個文件做測試。首先讀取文件蝎困,然后寫正則提取包名录语。

file = 'revolver_cohort.R'
text = readLines(paste(base_dir,file,sep='/'))
result1 = stringr::str_match_all(text,'^library\\((\\w+?)\\)')
result2 = stringr::str_match_all(text,'[^\\w](\\w+?):::?')

stringr包中的str_match_all可以提取單個字符的所有結(jié)果,對每個字符返回一個矩陣禾乘,其中()中的分組信息存儲在矩陣第二列及之后澎埠,多個結(jié)果為多行。注意始藕,此處的text為字符向量蒲稳,每個元素為文件中的一行。

下面為正則講解伍派,可能較為晦澀江耀。

result1提取的是類似library(some_package)中的包名。其中^表示從頭匹配诉植,因為library通常出現(xiàn)在一行的開頭祥国。\\(\\)對函數(shù)兩邊的括號進(jìn)行匹配,此處的第一個\對第二個\轉(zhuǎn)義晾腔,第二個\對有特殊含義的(進(jìn)行轉(zhuǎn)義尝蠕。內(nèi)部的()表示所關(guān)注的分組吞鸭。()內(nèi)部為\\w*蝶缀?,其中\w匹配字母或數(shù)字裳凸,第一個\用于轉(zhuǎn)義,+表示匹配1個或多個缤至,?為非貪婪模式潮罪。

result2提取的是類似some_package::some_function中的包名康谆。其中[^\\w]表示包名前的單個字符不能是字母或數(shù)字,[]為一組字符,內(nèi)部的^表示取反嫉到。之后的(\\w+?)為所關(guān)注的分組沃暗,和上面類似,匹配多個字母和數(shù)字何恶。最后的:::?中孽锥,?的出現(xiàn)是為了匹配0個或1個:,這種寫法是為了兼容可能出現(xiàn)的some_package:::some_function细层,三個冒號在R中被用于調(diào)用包內(nèi)部的函數(shù)惜辑。

str_match_all返回列表,列表元素對應(yīng)對text中每個字符元素處理的返回值疫赎,為矩陣盛撑。

result = c(result1,result2)
result = unlist(lapply(result,function(x){if(dim(x)[1]==0)return(NULL)else{return(x[,2])}}))

隨后連接result1result2。使用lapply捧搞,對每個列表元素進(jìn)行操作胎撇,當(dāng)dim(x)[1]==0即矩陣沒有值時返回NULL介粘,NULL之后在unlist結(jié)果中被忽略晚树,如果有元素就返回矩陣的第2列姻采。使用unlist進(jìn)行展平操作。

在實踐中爵憎,我們發(fā)現(xiàn)有這種情況席函。

    if (!is.na(D))
      cat(sprintf(' :: %s', D))

在第二行中督弓,result2能夠匹配到空字符''营曼。因此蒂阱,result中要刪除這種意外結(jié)果并去重。

packages = setdiff(unique(result),'')

試一下吧。

out:

"revolver"   "pio"        "clisymbols" "reshape2"

結(jié)果不錯录煤。

下一步就是寫個循環(huán)鳄厌,生成一個列表,將文件名作為元素的名稱妈踊。

base_dir = "../revolver-master/R"
files = list.files(base_dir)
all_packages = NULL
for (file in files) {
  text = readLines(paste(base_dir,file,sep='/'))
  result1 = stringr::str_match_all(text,'^library\\((\\w+?)\\)')
  result2 = stringr::str_match_all(text,'[^\\w](\\w+?):::?')
  result = c(result1,result2)
  result = unlist(lapply(result,function(x){if(dim(x)[1]==0)return(NULL)else{return(x[,2])}}))
  packages = setdiff(unique(result),'')
  if(length(packages)==0)next             
  packages = list(packages)             
  names(packages) = file                       # 直接用list(file = packages)的話了嚎,name就是file本身了。
  all_packages = append(all_packages,packages) # 使用append連接list
}
all_packages

out:

$color_palettes.R
[1] "RColorBrewer"

$compute_clone_trees.R
[1] "easypar" "ctree"   "pio"    

$compute_mutation_trees.R
[1] "easypar" "mtree"   "pio"    

$DET_index.R
[1] "vegan"

$input_custom_trees.R
[1] "easypar" "ctree"   "pio"    

$plot_CCF_histogram.R
[1] "reshape2"
······

其實也可以將得到的這些packages批量安裝一下廊营,看哪些可以順利安裝歪泳,哪些不能。

all_packages = unique(unlist(all_packages))
results = sapply(all_packages, function(x){
  if(x %in% row.names(installed.packages()))
    require(x,character.only = T)         #使用character.only = T獲取x內(nèi)含字符露筒,而不是require(x)
  else{
    try({install.packages(x);require(x,character.only = T)})
    }
  })

對包名進(jìn)行遍歷呐伞,已安裝的包require一下,看能否正常導(dǎo)入邀窃。未安裝的包先安裝后導(dǎo)入荸哟,使用try函數(shù),這樣當(dāng)安裝包錯誤時循環(huán)不會終止瞬捕。

最后的結(jié)果為鞍历,正常的情況下返回TRUE,錯誤的情況返回FALSE肪虎。因此可以提取出所有錯誤安裝的包劣砍。

names(results)[!results]

Bingo!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扇救,一起剝皮案震驚了整個濱河市刑枝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌迅腔,老刑警劉巖装畅,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異沧烈,居然都是意外死亡掠兄,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門锌雀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚂夕,“玉大人,你說我怎么就攤上這事腋逆⌒鲭梗” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵惩歉,是天一觀的道長等脂。 經(jīng)常有香客問我俏蛮,道長,這世上最難降的妖魔是什么慎菲? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任嫁蛇,我火速辦了婚禮,結(jié)果婚禮上露该,老公的妹妹穿的比我還像新娘睬棚。我一直安慰自己,他們只是感情好解幼,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布抑党。 她就那樣靜靜地躺著,像睡著了一般撵摆。 火紅的嫁衣襯著肌膚如雪底靠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天特铝,我揣著相機(jī)與錄音暑中,去河邊找鬼。 笑死鲫剿,一個胖子當(dāng)著我的面吹牛鳄逾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播灵莲,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼雕凹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了政冻?” 一聲冷哼從身側(cè)響起枚抵,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎明场,沒想到半個月后汽摹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡苦锨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年竖慧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逆屡。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖踱讨,靈堂內(nèi)的尸體忽然破棺而出魏蔗,到底是詐尸還是另有隱情,我是刑警寧澤痹筛,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站床佳,受9級特大地震影響砌们,放射性物質(zhì)發(fā)生泄漏浪感。R本人自食惡果不足惜饼问,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望峻堰。 院中可真熱鬧,春花似錦捐名、人聲如沸左冬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至光坝,卻和暖如春尸诽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背性含。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工绪商, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留腹殿,地道東北人理张。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像暂幼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子厨埋,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容