菜鸟学R语言:用R分析哪款相机性价比最高

May 06, 2013

Tags:菜鸟学R语言

题目起得很大。本文只是博主为了学习R和解决一些实际问题而写的,只用了R中最简单的函数,希望读者不要有误会。

之所以想分析比较“哪款相机(机身)性价比最高”,主要是因为最近有几个同学都打算买相机了,毕竟在欧洲景点很多,买个好相机来留下精彩的瞬间。我也是刚摄影入门,有点自己的心得,因为还是学生,收入微薄,不可能尝试很多好机器和镜头,然后再主观评测器材的好坏,一是没钱,二是没这个辨别能力。所以,我就想能否有个客观的数据分析能够指导我们选购呢?那就不得不说法国DxO实验室了。

法国DxO实验室(DxO Labs)位于法国布洛涅-比扬古(Boulogne-Billancourt),隶属于私有图像处理软件公司,旗下网站dxomark.com就是本文所用数据的来源。该公司所测试的相机涵盖了市面上大部分产品,采用工业级实验设备进行测试,并有数万计的镜头测试结果的数据库,所得到的测试评分可用来评估和比较数码相机和镜头的成像质量。

一般在相机新产品上市一段时间以后,Dxomark会经过测试给出该相机的评分。由于其专业性和中立性,经常会被器材党拿来讨论。本文采用的数据来源于:数码相机数据库评分(点击直达原链接)。接下来,我就说说我的菜鸟思路,是如何获取这些数据,并在R下面操作的。

首先,我打开了相机评分的网页,其评分分为:Overall score(总分)、Portrait(人像摄影)、Landscape(景观摄影)和Sports(运动摄影)三项。这三项的网页格式是一致的,因此只以总分数据的采集举例。

R

单击图中左下区域,右键选择“全选”,复制文本框中的数据,由于连图片也一起复制了,因此我们要粘贴到新建的一个txt文档中,以清除图片,并保留原文档的排列格式。然后在txt文档中直接全选复制粘贴到新建的excel里(注意粘贴时点击excel的第一个单元格),不作任何处理,另存为文本(text tab delimited)格式到Rstudio的工作路径即可。

下面就要转到Rstudio了,读取该txt文档,

cd=read.table("camera data.txt",header=F,sep="\t")

你会发现有很多NA、空白和重复值,没关系,下一步就要取其精华了。

R

先看每一款机型的名称、总分和排名共占有6个单元格,而整个表一共有1284行,因此共有1284/6=214款机型(当然这一步可以用函数代替,但我觉得对于格式杂乱的静态网页数据,还是具体问题具体分析的好)。下面就要写个循环来分别提取相机名称、相机总分和相机排名三列数据了。

cdname=cdscore=cdrank=factor() #这一步设置的原因未知,我是在debug时发现必须要先设置成factor才行
for (i in 1:214){
  cdname1=droplevels(cd[((i-1)*6+2),1])  #去掉多余的factor
  cdname1=data.frame(lapply(cdname1,as.character),stringsAsFactors=FALSE) #转换为字符数据框
  cdname=rbind(cdname,cdname1[1,1]) #合并行
  cdscore1=droplevels(cd[((i-1)*6+4),1])
  cdscore1=data.frame(lapply(cdscore1,as.character),stringsAsFactors=FALSE)
  cdscore=rbind(cdscore,cdscore1[1,1])
  cdrank1=droplevels(cd[((i-1)*6+5),1])
  cdrank1=data.frame(lapply(cdrank1,as.character),stringsAsFactors=FALSE)
  cdrank=rbind(cdrank,cdrank1[1,1])
}
cd1=cbind(cdrank,cdname,cdscore)
cd1=as.data.frame(cd1)
colnames(cd1) = c("ranks","camera names","overall scores")

此时的cd1就是这个样子了,

R

下面,我们开始提取dxomark.com上相机数据库的数据,因为里面有上市价格、相机类型、像素、重量、上市时间等数据(重量数据不全,价格数据不是现价,只做参考)。

R

像这样用鼠标选中数据区域,拉到最底下复制粘贴,和刚才的操作一样,该页面共有256款机型,包括了未测试的,我们选择每页显示50个项目,这样只需要重复操作6次就可得到所有数据,我承认这是非常笨的方法,只适合菜鸟。但我觉得对于这种非动态更新的网页静态数据,没有万金油的方法可以套,毕竟主动权掌握在网页设计者手中。所以,我认为掌握一些笨方法对于极小数据量是很有用的。然后我们就得到了,

R

同样,也有很多空行和NA值,并且有几十款机型由于各种原因,DxOmark没有评分,因此我们只选需要的,

cdb=cdb[which(cdb$Mpix != 'NA'),] #发现数据框规律,通过反选Mpix为NA的列
cdbtested=cdb[which(cdb$Image == 'TESTED'),] #选择经过测试的机型

恰巧,得到的cdbtested也是214款机器。

R

接下来,要重新对cd1和cdbtested进行重新排列和合并。

#in order by camera names
cd1ordered=cd1[order(cd1[,2]),]
cdbtd=cdbtested[order(cdbtested[,2]),]
cdnew=cbind(cd1ordered,cdbtd[,-1])

你会发现数据框是字符格式,而且有的单元格是数字+单位的形式,为了对数据进行分析,我们需要去掉单位,将其转换为numeric格式。例如,把portrait分数中的22 bits,改成22。

cdnew[,4] = sub('.....$','',cdnew[,4])

其他依次类推。

下面,我们要把需要进行数据运算分析的列,从character转换成numeric

cdnew1=cdnew
cdnew1=droplevels(cdnew1)
cdnew1=data.frame(lapply(cdnew1,as.character),stringsAsFactors=FALSE)
cdnew1[,c(1,2,3,4,5,6,7,8,11,12,15)] =as.numeric(as.matrix(cdnew1[,c(1,2,3,4,5,6,7,8,11,12,15)]))

并修改一些数据转换产生的错误,比如4:3大小的传感器,被R识别为某种运算,所有4:3的单元格都成了0.16875,因此,也要排除这些转换错误,还好,数据量比较小,容易发现。这可能是我对数据格式不熟悉,造成的,应该可以通过修改代码解决。然后选择

cdnew1[which(cdnew1[,13]=='0.16875'),13] = '4:3'
cdnew1[which(cdnew1[,15]==0),15] = NA #一些空值为0,我们也不需要,所以一并转换为NA

以上就完成了所有数据的采集过程,我用了一晚上,因为很多基础的知识不熟悉,需要搜索才能解决,其实后来再看R in Action这本书的时候,发现如果要用好R,还是要重头学起,不能断章取义(以上代码多少也有断章取义的,只做到解决问题,至于代码效率就没有考虑,也没有能力考虑了)。

接下来,要考虑如何分析这些数据了。先谈谈自己的看法,性价比这个东西很难界定,所以每个人要先设定自己的阈值,比如价格设在500美元,机器重量设在500g,就很满意了。当然,类似于像素等其他参数也可以考虑。这样的话,我考虑的性价比就包括了价格、机身重量和性能三项。公式很简单,

性价比指数 = 性能分数 / (价格 / 500 * 100)/ (机身重量 / 500 * 100)

价格和机身重量要乘以100是为了转换成和性能分数一致的百分制(此处很值得研究)。

然后我得到的结果是(代码就不放了),cdfinalscore越高,性价比越高。

R

R

可见莱卡M9有多坑爹啊。

以上仅供个人参考,大家可以根据自己的喜好,设置不同的参数分析,对排名影响还是挺大的。下一步,我都想学学Python,定期抓取亚马逊的价格数据了。哎,时间不够用啊,不能不务正业啊。如果,这一块能做好,搞个小网站赚钱还是有搞头的。

P.S. 以上文中代码问题还请各位指正,纯新手和菜鸟,没有什么好的代码习惯。欢迎大家交流。

· The end ·