R包:reticulate: R对python的接口包

reticulate: R对python的接口包

R和python是两种不同的编程语言,前者是统计学家发明并且服务数学统计计算,后者则是最万能的胶水语言。随着大数据时代的到来,两者在数据分析领域存在越来越多的共同点且可以相互使用,为了破解二者的编程壁垒,CRAN收录了具有R接口的python包,从而使得两类语言的数据能共同使用。

介绍[1]

reticulate[2] 是用于Python和R之间协同操作的全套工具,在RRstudio中均可使用;要求Rstudio必须在1.2版本以上;

install.packages("reticulate")
library(reticulate)

特性

  • reticulate 在R中支持多种方式调用python;
  • 实现R和python对象之间的转换;
  • 随意切换不同版本的python;
  • R内使用$调用python对象;
  • python内使用.调用R对象;
  • 使用import函数导入python模块import("os");
  • source_python()获取任何Python脚本;
  • 使用repl_python()交互使用python;

范例

Rpython对同一数据进行可视化,可视化图形包括scatterplotboxplotbarplotheatmap

散点图

R代码

library(dplyr)
library(ggplot2)

iris %>% mutate(Species=factor(Species, levels = c("setosa", "versicolor", "virginica"))) %>%
  ggplot(aes(x=Sepal.Width, y=Petal.Width, color=Species))+
  geom_point()+
  guides(color=guide_legend("", keywidth = .5, keyheight = .5))+
  labs(title = 'Scatter plot')+
  theme_bw()+
  scale_color_manual(values = c("red", "green", "blue"))+
  theme(plot.title = element_text(size = 10, color = "black", face = "bold", hjust = 0.5), 
      axis.title = element_text(size = 10, color = "black", face = "bold"),
      axis.text = element_text(size = 9, color = "black"),
      text = element_text(size = 8, color = "black"),
      strip.text = element_text(size = 9, color = "black", face = "bold"),
      panel.grid = element_blank(),
      legend.position = c(1, 1),
      legend.justification = c(1, 1),
      legend.background = element_rect(fill="white", color = "black"))

Python代码

dat = r.iris  # Python调用R内嵌数据使用r.data
species_map = {'setosa':1, 'versicolor':2, 'virginica':3}
dat['Species'] = dat['Species'].map(species_map)

import numpy as np
import matplotlib.pyplot as plt
# plt.scatter(dat['Sepal.Width'], dat['Petal.Width'], c=dat['Species'],
#      alpha=0.8, edgecolors='none', s=30, label=["1", "2", "3"])
# plt.title('Scatter plot in iris')
# plt.xlabel('Sepal.Width (cm)')
# plt.ylabel('Petal.Width (cm)')
# plt.legend(loc=1)
# plt.show()
 
dat1 = (np.array(dat[dat.Species==1]['Sepal.Width']), 
        np.array(dat[dat.Species==1]['Petal.Width']))
dat2 = (np.array(dat[dat.Species==2]['Sepal.Width']), 
        np.array(dat[dat.Species==2]['Petal.Width']))
dat3 = (np.array(dat[dat.Species==3]['Sepal.Width']), 
        np.array(dat[dat.Species==3]['Petal.Width']))

mdat = (dat1, dat2, dat3)
colors = ("red", "green", "blue")
groups = ("setosa", "versicolor", "virginica")

# step1 build figure background
fig = plt.figure()

# step2 build axis
ax  = fig.add_subplot(1, 1, 1, facecolor='1.0')  

# step3 build figure
for data, color, group in zip(mdat, colors, groups):
  x, y = data
  ax.scatter(x, y, alpha=0.8, c=color, 
      edgecolors='none', s=30, label=group)      

plt.title('Scatter plot')
plt.legend(loc=1)  

# step4 show figure in the screen
plt.show() 

箱形图

R代码

library(dplyr)
library(ggplot2)

iris %>% mutate(Species=factor(Species, levels = c("setosa", "versicolor", "virginica"))) %>%
  ggplot(aes(x=Species, y=Sepal.Width, fill=Species))+
  stat_boxplot(geom = "errorbar", width = .12)+
  geom_boxplot(width = .3, outlier.shape = 3, outlier.size = 1)+
  guides(fill=guide_legend(NULL, keywidth = .5, keyheight = .5))+
  xlab("")+
  theme_bw()+
  scale_fill_manual(values = c("red", "green", "blue"))+
  theme(plot.title = element_text(size = 10, color = "black", face = "bold", hjust = 0.5), 
      axis.title = element_text(size = 10, color = "black", face = "bold"),
      axis.text = element_text(size = 9, color = "black"),
      text = element_text(size = 8, color = "black"),
      strip.text = element_text(size = 9, color = "black", face = "bold"),
      panel.grid = element_blank(),
      legend.position = c(1, 1),
      legend.justification = c(1, 1),
      legend.background = element_rect(fill="white", color = "black"))

Python代码

dat = r.iris  # Python调用R内嵌数据使用r.data
species_map = {'setosa':1, 'versicolor':2, 'virginica':3}
dat['Species'] = dat['Species'].map(species_map)

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

dat11 = (np.array(dat[dat.Species==1]['Sepal.Width']))
dat21 = (np.array(dat[dat.Species==2]['Sepal.Width']))
dat31 = (np.array(dat[dat.Species==3]['Sepal.Width']))

mdat2 = (dat11, dat21, dat31)
colors = ("red", "green", "blue")
groups = ("setosa", "versicolor", "virginica")

fig = plt.figure()
axes = fig.add_subplot(facecolor='1.0')
bplot = axes.boxplot(mdat2, patch_artist=True, notch=0, sym='+', vert=1, whis=1.5,
  whiskerprops = dict(linestyle='--',linewidth=1.2, color='black'))

# color
for patch, color in zip(bplot['boxes'], colors):
  patch.set_facecolor(color)

# axes labels
plt.setp(axes, xticks=[1,2,3],
         xticklabels=["setosa", "versicolor", "virginica"])

red_patch = mpatches.Patch(color='red', label='setosa')
green_patch = mpatches.Patch(color='green', label='versicolor')
blue_patch = mpatches.Patch(color='blue', label='virginica')

plt.legend(handles=[red_patch, green_patch, blue_patch], loc=1)

plt.show()

条形图

R代码

library(dplyr)
library(ggplot2)

iris %>% mutate(Species=factor(Species, levels = c("setosa", "versicolor", "virginica"))) %>%
  select(Species, Sepal.Width) %>% group_by(Species) %>%
  summarize(avg=mean(Sepal.Width), n=n(), sd=sd(Sepal.Width), se=sd/sqrt(n)) %>%
  ungroup() %>%
  ggplot(aes(x=Species, y=avg, fill=Species))+
  geom_bar(stat="identity", width=.4, color="black")+
  geom_errorbar(aes(ymin=avg-sd, ymax=avg+sd), width=.15,
                 position=position_dodge(.9), size=1)+
  guides(fill=guide_legend(NULL, keywidth = .5, keyheight = .5))+
  xlab("")+
  ylab("Sepal.Width")+
  scale_y_continuous(breaks=seq(0, 3.5,0.5), limits=c(0, 4.4),expand = c(0,0))+
  theme_bw()+
  scale_fill_manual(values = c("red", "green", "blue"))+
  theme(axis.title = element_text(size = 10, color = "black", face = "bold"),
      axis.text = element_text(size = 9, color = "black"),
      text = element_text(size = 8, color = "black"),
      strip.text = element_text(size = 9, color = "black", face = "bold"),
      panel.grid = element_blank(),
      legend.position = c(1, 1),
      legend.justification = c(1, 1),
      legend.background = element_rect(fill="white", color = "black"))

Python代码

dat = r.iris  # Python调用R内嵌数据使用r.data
species_map = {'setosa':1, 'versicolor':2, 'virginica':3}
dat['Species'] = dat['Species'].map(species_map)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

mean = list(dat['Sepal.Width'].groupby(dat['Species']).mean())
sd   = list(dat.groupby('Species').agg(np.std, ddof=0)['Sepal.Width'])

df = pd.DataFrame({'mean':mean}, index=["setosa", "versicolor", "virginica"])
df.plot(kind='bar', alpha=0.75, rot=0, edgecolor='black', 
        yerr=sd, align='center', ecolor='black', capsize=5,
        color=("red", "green", "blue"),
        ylim=(0.0, 4.4),
        yticks=list(np.arange(0, 4.0, 0.5)))

# xlabel
plt.xlabel('')
plt.ylabel('Sepal.Width')

# legend
red_patch = mpatches.Patch(color='red', label='setosa')
green_patch = mpatches.Patch(color='green', label='versicolor')
blue_patch = mpatches.Patch(color='blue', label='virginica')
plt.legend(handles=[red_patch, green_patch, blue_patch],   # color and group
    loc=1,                # location
    prop={'size': 8})     # size 
plt.show()

热图

R代码

library(dplyr)
library(ggplot2)

get_upper_tri <- function(x){
  x[upper.tri(x)] <- NA 
  return(x)
}

round(cor(mtcars[, c(1:7)], method = "spearman"), 2) %>% 
  get_upper_tri() %>% reshape2::melt(na.rm = TRUE) %>% 
  
  ggplot(aes(x=Var1, y=Var2, fill=value))+
  geom_tile(color = "white")+
  scale_fill_gradient2(low = "blue", high = "red", mid = "white", 
   midpoint = 0, limit = c(-1,1), space = "Lab", name="Spearman\nCorrelation")+
  theme_minimal()+
  guides(fill = guide_colorbar(barwidth = 7, barheight = 1,
                title.position = "top", title.hjust = 0.5))+
  coord_fixed()+
  geom_text(aes(label = value), color = "black", size = 4)+
  theme(axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    axis.text.x = element_text(angle = 45, vjust = 1, size = 12, hjust = 1),
    panel.grid.major = element_blank(),
    panel.border = element_blank(),
    panel.background = element_blank(),
    axis.ticks = element_blank(),
    legend.justification = c(1, 0),
    legend.position = c(0.6, 0.7),
    legend.direction = "horizontal")

Python代码

import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

corr = r.mtcars.corr()
mask = np.zeros_like(corr)
mask[np.triu_indices_from(mask)] = True

f, ax = plt.subplots(figsize=(6, 5))
heatmap = sns.heatmap(corr, vmin=-1, vmax=1, mask=mask, center=0,
  # , orientation='horizontal'
  cbar_kws=dict(shrink=.4, label='Spearman\nCorrelation', ticks=[-.8, -.4, 0, .4, .8]),
  annot_kws={'size': 8, 'color': 'white'},
  #cbar_kws = dict(use_gridspec=False,location="right"), 
  linewidths=.2, cmap = 'seismic', square=True, annot=True,
  xticklabels=corr.columns.values,
  yticklabels=corr.columns.values)

#add the column names as labels
ax.set_xticklabels(corr.columns, rotation = 45)
ax.set_yticklabels(corr.columns)
sns.set_style({'xtick.bottom': True}, {'ytick.left': True})

#heatmap.get_figure().savefig("heatmap.pdf", bbox_inches='tight')

plt.show()

心得

初次使用reticulate的感觉还不错,可以比较完美串联R和Python,尤其是在Rmarkdown文件内使用R和Python代码,但缺点也很明显:

  • 运行Python cell没有详细报错信息;
  • 粗略的报错提示行信息不以Rmd文件整体行作为开始;
  • 无法兼容带有汉字的注释信息;
  • 无法像R一样查看python环境下变量;
  • 出错后有时无任何报错信息

根据visual studio code的最新python插件公布情况看,以后vsc可以完美兼容Jupyter notebook格式文件,因此如果想单独使用python但无较好交互编辑器,可以使用vsc的python插件读取ipynb文件[3]

参考


  1. https://zhuanlan.zhihu.com/p/35049732

  2. https://github.com/rstudio/reticulate

  3. https://code.visualstudio.com/docs/python/jupyter-support

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342