zoukankan      html  css  js  c++  java
  • 深入对比数据科学工具箱:Python和R之争

    建议:
    如果只是处理(小)数据的,用R。结果更可靠,速度可以接受,上手方便,多有现成的命令、程序可以用。
    要自己搞个算法、处理大数据、计算量大的,用python。开发效率高,一切尽在掌握。

    概述

    在真实的数据科学世界里,我们会有两个极端,一个是业务,一个是工程。偏向业务的数据科学被称为数据分析(Data Analysis),也就是A型数据科学。偏向工程的数据科学被称为数据构建(Data Building),也就是B型数据科学。

    从工具上来看,按由业务到工程的顺序,这个两条是:EXCEL >> R >> Python >> Scala

    在实际工作中,对于小数据集的简单分析来说,使用EXCEL绝对是最佳选择。当我们需要更多复杂的统计分析和数据处理时,我们就需要转移到 Python 和 R 上。在确定工程实施和大数据集操作时,我们就需要依赖 Scala 的静态类型等工程方法构建完整的数据分析系统。

    Scala 和 Excel 是两个极端,对于大多数创业公司而言,我们没有足够多的人手来实现专业化的分工,更多情况下,我们会在 Python 和 R 上花费更多的时间同时完成数据分析(A型)和数据构建(B型)的工作。而许多人也对 Python 和 R 的交叉使用存在疑惑,所以本文将从实践角度对 Python 和 R 中做了一个详细的比较。

    应用场景对比

    应用Python的场景

    • 网络爬虫/抓取:尽管 rvest 已经让 R 的网络爬虫/抓取变得容易,但 Python 的 beautifulsoup 和 Scrapy 更加成熟、功能更强大,结合django-scrapy我们可以很快的构建一个定制化的爬虫管理系统。

    • 连接数据库: R 提供了许多连接数据库的选择,但 Python 只用 sqlachemy 通过ORM的方式,一个包就解决了多种数据库连接的问题,且在生产环境中广泛使用。Python由于支持占位符操作,在拼接SQL语句时也更加方便。

    • 内容管理系统:基于Django,Python可以快速通过ORM建立数据库、后台管理系统,而R中的 Shiny 的鉴权功能暂时还需要付费使用。

    • API构建:通过Tornado这个标准的网络处理库,Python也可以快速实现轻量级的API,而R则较为复杂。

    应用R的场景

    • 统计分析: 尽管 Python 里 Scipy、Pandas、statsmodels 提供了一系列统计工具 ,R 本身是专门为统计分析应用建立的,所以拥有更多此类工具。

    • 互动式图表/面板: 近来 bokeh、plotly、 intuitics 将 Python 的图形功能扩展到了网页浏览器,甚至我们可以用tornado+d3来进一步定制可视化页面,但 R 的 shiny 和 shiny dashboard 速度更快,所需代码更少。

    此外,当今数据分析团队拥有许多技能,选择哪种语言实际上基于背景知识和经验。对于一些应用,尤其是原型设计和开发类,工作人员使用已经熟悉的工具会比较快速。

    数据流编程对比

    接着,我们将通过下面几个方面,对Python 和 R 的数据流编程做出一个详细的对比。

    1. 参数传递

    2. 数据读取

    3. 基本数据结构对照

    4. 矩阵转化

    5. 矩阵计算

    6. 数据操作

    参数传递

    Python/R 都可以通过命令行的方式和其他语言做交互,通过命令行而不是直接调用某个类或方法可以更好地降低耦合性,在提高团队协作的效率。

    参数传递PythonR
    命令行输入 Python path/to/myscript.py arg1 arg2 arg3 Rscript path/to/myscript.R arg1 arg2 arg3
    脚本识别 import sys my_args = sys.argv myArgs <- commandArgs(trailingOnly = TRUE)

    数据传输与解析

    对于数据传输与解析,我们首推的格式是csv,因为一方面,csv格式的读写解析都可以通过 Python 和 R 的原生函数完成,不需要再安装其他包。另一方面,csv格式可以很快的转化为 data frame 格式,而data frame 格式是数据流分析的核心。

    不过,实际情况中,我们需要传输一些非结构化的数据,这时候就必须用到 JSNO 或者 YAML。

    数据传输与解析PythonR
    CSV(原生) csv read.csv
    CSV(优化) pandas.read_csv("nba_2013.csv") data.table::fread("nba_2013.csv")
    JSON json(原生) jsonlite
    YAML PyYAML yaml

    基本数据结构

    由于是从科学计算的角度出发,R 中的数据结构非常的简单,主要包括 向量(一维)、多维数组(二维时为矩阵)、列表(非结构化数据)、数据框(结构化数据)。而 Python 则包含更丰富的数据结构来实现数据更精准的访问和内存控制,多维数组(可读写、有序)、元组(只读、有序)、集合(唯一、无序)、字典(Key-Value)等等。

    基本数据结构PythonR
    数组 list:[1,'a'] :array:array(c(1,"a"),2)
    Key-Value(非结构化数据) 字典:["a":1] lists
    数据框(结构化数据) dataframe data.frame

    Python dict 操作:dict["key"] 或者 dict.get("key","default_return")R list 操作: list["key"] 或者 list$key

    R 中数据结构转化(plyr)listdata framearray
    list llply() ldply() laply()
    data frame dlply() ddply() daply()
    array alply() adply() aaply()

    MapReduce

    PythonR
    map Map
    reduce Reduce
    filter filter

    矩阵操作

    实际上,Python(numpy) 和 R中的矩阵都是通过一个多维数组(ndarray)实现的。

    矩阵转化PyhtonR
    维度 data.shape dim(data)
    转为向量 data.flatten(1) as.vector(data)
    转为矩阵 np.array([[1,2,3],[3,2,1]]) matrix(c(1,2,3,3,2,1),nrow=2,byrow=T)
    转置 data.T t(data)
    矩阵变形 data.reshape(1,np.prod(data.shape)) matrix(data,ncol=nrow(data)*ncol(data))
    矩阵按行拼接 np.r_[A,B] rbind(A,B)
    矩阵按列拼接 np.c_[A,B] cbind(A,B)
    矩阵计算PyhtonR
    矩阵乘法 np.dot(A,B) A %*% B
    矩阵幂指 np.power(A,3) A^3
    全零矩阵 np.zeros((3,3)) matrix(0,nrow=3,ncol=3)
    矩阵求逆 np.linalg.inv(A) solve(A)
    协方差 np.cov(A,B) cov(A,B)
    特征值 np.linalg.eig(A)[0] eigen(A)$values
    特征向量 np.linalg.eig(A)[1] eigen(A)$vectors

    数据框操作

    参考 R 中的 data frame 结构,Python 的 Pandas包也实现了类似的 data frame 数据结构。现在,为了加强数据框的操作,R 中更是演进出了 data table 格式(简称dt),这种格式以 dt[where,select,group by] 的形式支持类似SQL的语法。

    数据框操作PythonR
    按Factor的Select操作 df[['a', 'c']] dt[,.(a,c),]
    按Index的Select操作 df.iloc[:,1:2] dt[,1:2,with=FALSE]
    按Index的Filter操作 df[1:2] dt[1:2]
    groupby分组操作 df.groupby(['a','b'])[['c','d']].mean() aggregate(x=dt[, c("v1", "v2")], by=list(mydt2$by1, mydt2$by2), FUN = mean)
    %in% 匹配操作 返回T/F pd.Series(np.arange(5),dtype=np.float32).isin([2, 4]) 0:4 %in% c(2,4)
    match 匹配操作 返回Index pd.Series(pd.match(pd.Series(np.arange(5),dtype=np.float32),[2,4],np.nan)) match(0:4, c(2,4))
    tapply df.pivot_table(values='a', columns='c', aggfunc=np.max) tapply(dt$a,dt$c,max)#其中dt$a是numeric,dt$c是nominal
    查询操作 df[df.a <= df.b] dt[ a<=b ]
    with操作 pd.DataFrame({'a': np.random.randn(10), 'b': np.random.randn(10)}).eval('a + b') with(dt,a + b)
    plyr操作 df.groupby(['month','week']).agg([np.mean, np.std]) ddply(dt, .(month, week), summarize,mean = round(mean(x), 2),sd = round(sd(x), 2))
    多维数组融合 pd.DataFrame([tuple(list(x)+[val]) for x, val in np.ndenumerate(np.array(list(range(1,24))+[np.NAN]).reshape(2,3,4))]) data.frame(melt(array(c(1:23, NA), c(2,3,4))))
    多维列表融合 pd.DataFrame(list(enumerate(list(range(1,5))+[np.NAN]))) data.frame(melt(as.list(c(1:4, NA))))
    数据框融合 pd.melt(pd.DataFrame({'first' : ['John', 'Mary'],'last' : ['Doe', 'Bo'],'height' : [5.5, 6.0],'weight' : [130, 150]}), id_vars=['first', 'last']) melt(data.frame(first = c('John', 'Mary'),last = c('Doe', 'Bo'),height = c(5.5, 6.0),weight = c(130, 150), id=c("first", "last"))
    数据透视表 pivot table pd.pivot_table(pd.melt(pd.DataFrame({ 'x': np.random.uniform(1., 168., 12), 'y': np.random.uniform(7., 334., 12), 'z': np.random.uniform(1.7, 20.7, 12), 'month': [5,6,7]4, 'week': [1,2]6}), id_vars=['month', 'week']), values='value', index=['variable','week'],columns=['month'], aggfunc=np.mean) acast(melt(data.frame(x = runif(12, 1, 168),y = runif(12, 7, 334),z = runif(12, 1.7, 20.7),month = rep(c(5,6,7),4),week = rep(c(1,2), 6)), id=c("month", "week")), week ~ month ~ variable, mean)
    连续型数值因子分类 pd.cut(pd.Series([1,2,3,4,5,6]), 3) cut(c(1,2,3,4,5,6), 3)
    名义型因子分类 pd.Series([1,2,3,2,2,3]).astype("category") factor(c(1,2,3,2,2,3))

    数据流编程对比的示例

    Python 的 Pandas 中的管道操作
      (df
       .groupby(['a', 'b', 'c'], as_index=False)
       .agg({'d': sum, 'e': mean, 'f', np.std})
       .assign(g=lambda x: x.a / x.c)
       .query("g > 0.05")
       .merge(df2, on='a'))
    R 的 dplyr 中的管道操作
    flights %>% group_by(year, month, day) %>%
      select(arr_delay, dep_delay) 
    
      summarise(
    
        arr = mean(arr_delay, na.rm = TRUE),
    
        dep = mean(dep_delay, na.rm = TRUE)) %>%
    
      filter(arr > 30 | dep > 30)

    数据可视化对比

    绘制相关性散点图

    对比数据相关性是数据探索常用的一种方法,下面是Python和R的对比。

    Python
    import seaborn as sns
    import matplotlib.pyplot as plt
    sns.pairplot(nba[["ast", "fg", "trb"]])
    plt.show()

    R
    library(GGally)
    ggpairs(nba[,c("ast", "fg", "trb")])

    虽然我们最终得到了类似的图形,这里R中GGally是依赖于ggplot2,而Python则是在matplotlib的基础上结合Seaborn,除了GGally在R中我们还有很多其他的类似方法来实现对比制图,显然R中的绘图有更完善的生态系统。

    绘制聚类效果图

    这里以K-means为例,为了方便聚类,我们将非数值型或者有确实数据的列排除在外。

    Python
    from sklearn.cluster import KMeans
    kmeans_model = KMeans(n_clusters=5, random_state=1)
    good_columns = nba._get_numeric_data().dropna(axis=1)
    kmeans_model.fit(good_columns)
    labels = kmeans_model.labels_
    
    from sklearn.decomposition import PCA
    pca_2 = PCA(2)
    plot_columns = pca_2.fit_transform(good_columns)
    plt.scatter(x=plot_columns[:,0], y=plot_columns[:,1], c=labels)
    plt.show()

    R
    library(cluster)
    set.seed(1)
    isGoodCol <- function(col){
       sum(is.na(col)) == 0 && is.numeric(col) 
    }
    goodCols <- sapply(nba, isGoodCol)
    clusters <- kmeans(nba[,goodCols], centers=5)
    labels <- clusters$cluster
    
    nba2d <- prcomp(nba[,goodCols], center=TRUE)
    twoColumns <- nba2d$x[,1:2]
    clusplot(twoColumns, labels)

    速度对比

    Python
    import numpy as np
    xx = np.zeros(100000000)
    %timeit xx[:] = 1
    The slowest run took 9.29 times longer than the fastest. This could mean that an intermediate result is being cached 
    1 loops, best of 3: 111 ms per loop
    R
    xx <- rep(0, 100000000)
    system.time(xx[] <- 1)
    user  system elapsed 
      1.326   0.103   1.433

    显然这里 R 1.326的成绩 比 Python 的 Numpy 3:111 的速度快了不少。

    事实上,现在 R 和 Python 的数据操作的速度已经被优化得旗鼓相当了。下面是R中的 data.table、dplyr 与 Python 中的 pandas 的数据操作性能对比:

    我曾经用data.table和pandas分别读取过一个600万行的IOT数据,反复10次,data.table以平均10s的成绩胜过了pandas平均15s的成绩,所以在IO上我倾向于选择使用data.table来处理大数据,然后喂给spark和hadoop进行进一步的分布式处理。

    R

    summary(fit)
    
    ##结果
    Call:
    lm(formula = ast ~ fg, data = train)
    
    Residuals:
        Min      1Q  Median      3Q     Max 
    -228.26  -35.38  -11.45   11.99  559.61
    [output truncated]
    


    Python

    import statsmodels.formula.api as sm
    model = sm.ols(formula='ast ~ fga', data=train)
    fitted = model.fit()
    fitted.summary()
    
    ##结果
    Call:
    lm(formula = ast ~ fg, data = train)
    
    Residuals:
        Min      1Q  Median      3Q     Max 
    -228.26  -35.38  -11.45   11.99  559.61
    [output truncated]
    


    通过以上对比:

    R在做统计分析,更加简单粗暴!毕竟R是统计科班出身嘛

    结论

    Python 的 pandas 从 R 中偷师 dataframes,R 中的 rvest 则借鉴了 Python 的 BeautifulSoup,我们可以看出两种语言在一定程度上存在的互补性,通常,我们认为 Python 比 R 在泛型编程上更有优势,而 R 在数据探索、统计分析是一种更高效的独立数据分析工具。所以说,同时学会Python和R这两把刷子才是数据科学的王道。

     [转自]:https://segmentfault.com/a/1190000004879349

    即使只是凡世中一颗小小的尘埃,命运也要由自己主宰,像向日葵般,迎向阳光、勇敢盛开
  • 相关阅读:
    [转发]深入理解git,从研究git目录开始
    iOS系统网络抓包方法
    charles抓包工具
    iOS多线程中performSelector: 和dispatch_time的不同
    IOS Core Animation Advanced Techniques的学习笔记(五)
    IOS Core Animation Advanced Techniques的学习笔记(四)
    IOS Core Animation Advanced Techniques的学习笔记(三)
    IOS Core Animation Advanced Techniques的学习笔记(二)
    IOS Core Animation Advanced Techniques的学习笔记(一)
    VirtualBox复制CentOS后提示Device eth0 does not seem to be present的解决方法
  • 原文地址:https://www.cnblogs.com/lantingg/p/9448809.html
Copyright © 2011-2022 走看看