我在写FPTree算法时,使用linux下的split
命令将一个transaction.txt文件分成了10个分区文件“transaction.aa~ transaction.aj”,而我想得到这样的文件命名“transaction.00~ transaction.09”。我去研究split
命令的参数,看能不能直接分割文件后输出以数字结尾的文件名,无功而返。我又去研究mv
命令的参数,希望能直接使用一次mv
修改所有的文件名成想要的名字,也是无功而返。当然这期间,我会上网搜索有没有相关的解决方案。而最后我的解决方法是:在编辑器sublime text2里写一条mv transaction.aa transaction.00
,然后复制到10行,手动将a替换成相应字母,再将0替换成相应数字,最后就是这样的效果。
mv transaction.aa transaction.00
mv transaction.ab transaction.01
mv transaction.ac transaction.02
mv transaction.ad transaction.03
mv transaction.ae transaction.04
mv transaction.af transaction.05
mv transaction.ag transaction.06
mv transaction.ah transaction.07
mv transaction.ai transaction.08
mv transaction.aj transaction.09
然后,我复制,再在linux终端下粘贴,运行,完成全部文件名字的修改,总耗时不超过30秒。我本想更加高效地解决问题,一个命令,一个函数就可以解决。甚至专门写一个函数处理,只要能不手动一条条处理即可。而事实上,即便我在终端下一条条地手写mv,也比上面的聪明方法花的时间都少,也不会超过2分钟。而上面的例子稍作改进,依然是使用笨方法,时间就已经不足半分钟了。
使用网络找答案,面临两个问题,一描述清自己的问题,二找到网上正确的答案。这两个问题真的很难,平时面对面与人交流描述生活的问题已经很难,每每遇到自己说了一堆,对方问:你说什么?此时涌起不是抽自己一大嘴巴就是赏对方一耳光的冲动。而在网上还要描述清技术问题,更是难中之难。比如程序员界经常唠叨的一个现象就是某程序员遇到了问题A,自己有解决思路B,但又遇到阻碍,然后各种向人咨询B相关问题,结果最终被问的某个人发现此程序员想解决的是问题A,然后他给出一个成功的解决方案C。在生活中,与人沟通的成本非常高,网络上,修正自己的问题和尝试所搜寻答案的对错,都有非常高的成本。我室友培总某日加班回来跟我们说:“今天公司上不了网,结果我一下午干了比前3天还多的活”。我想除了平时上网休闲的因素,这个现象也一定程度证明了自己解决问题比上网搜资料有效很多吧。捷径往往意味着更长的路,网络上可以找到解决你问题的答案就像一个可怕的走捷径的诱惑,因为它会让人习以为常。
在使用R语言工作的过程中,我还遇到了很多类似的例子。有过很多次教训,为我脑子里的设想的高效解决方案在网上各种一通找。甚至为同一个问题找过多次,最后却无功而返。而在我无心插柳的时候,比如看R某库的函数的demo时,发现其中某行代码正好是解决我之前遇到的某数据处理的一种简洁高效方法。有的问题的简洁高效方法可能就是一特殊函数,你知道它,你就能很快搞定问题。而有的简洁高效方法体现的是一种解决方式,你理解了它,相通的问题都能找到高效方法了。
这个问题困难在于,我只能得到字符串类型的变量名,无法引用这个变量对象,使用的笨方法是,把交互代码打印出来,再去除"符号,把交互代码粘贴进去执行。
idvar都是字符串类型的变量名,执行下面代码
for (idvar in idvars)
print(paste("base.dpi.equal$",idvar,"<-","as.factor(","base.dpi.equal$",idvar,")")
得到
"base.dpi.equal$USER_ID <- as.factor( base.dpi.equal$USER_ID )"
"base.dpi.equal$ACCT_BRAND_ID <- as.factor( base.dpi.equal$ACCT_BRAND_ID )"
"base.dpi.equal$AGE_ID <- as.factor( base.dpi.equal$AGE_ID )"
"base.dpi.equal$BRAND_ID <- as.factor( base.dpi.equal$BRAND_ID )"
"base.dpi.equal$CALL_COUNTS_ID <- as.factor( base.dpi.equal$CALL_COUNTS_ID )"
"base.dpi.equal$CALL_DURATION_M_ID <- as.factor( base.dpi.equal$CALL_DURATION_M_ID )"
"base.dpi.equal$CHANNEL_ID <- as.factor( base.dpi.equal$CHANNEL_ID )"
复制放到sublime text2里,替换掉"符号,得到下面的代码,粘贴到交互行执行
base.dpi.equal$USER_ID <- as.factor( base.dpi.equal$USER_ID )
base.dpi.equal$ACCT_BRAND_ID <- as.factor( base.dpi.equal$ACCT_BRAND_ID )
base.dpi.equal$AGE_ID <- as.factor( base.dpi.equal$AGE_ID )
base.dpi.equal$BRAND_ID <- as.factor( base.dpi.equal$BRAND_ID )
base.dpi.equal$CALL_COUNTS_ID <- as.factor( base.dpi.equal$CALL_COUNTS_ID )
base.dpi.equal$CALL_DURATION_M_ID <- as.factor( base.dpi.equal$CALL_DURATION_M_ID )
base.dpi.equal$CHANNEL_ID <- as.factor( base.dpi.equal$CHANNEL_ID )
使用这些笨方法虽然代码量大,但并不耗时,主要是粘贴复制和字符串处理的功夫。我好几次不想使用这个笨方法,又跑到网上找,跑到论坛问,问如何将字符串转化为变量之类,答案很少,找到的也都不好使。这又耗费我的宝贵的时间,验证拖慢了我的工作节奏。直到我无意中在某函数demo里发现相关代码。最后上面的问题有了个简洁的方法。
#将字符串转化为表达式执行,解决了字符串不能作为变量名的问题
for (idvar in idvars)
exp = parse(text=paste("base.dpi.equal$",idvar,"<-","as.factor(","base.dpi.equal$",idvar,")") #将字符串转化为表达式执行
eval(exp) #执行表达式
前面的解决方案已经可以修改数据库,读取自然不在话下。我开始一段时间使用都是循环打印的方法,而实际上,读取数据量的每一个变量可以十分十分简洁。
#查看一个数据框的各变量是否有缺失值
sapply(product, f <- function(x){ return(sum(is.na(x))})
#sapply函数就是对第一个参数(数据框)的每一个变量依次应用第二个参数(f函数)
这些问题我在网上都找过,并非网上没有这些问题的答案,而是当我还不够熟悉R语言中处处体现着向量整体运算思维,避免循环思想时,我是很难描述清我的问题的,而即便我看到相近的答案,我也很可能依葫芦画瓢地使用却没能奏效。同样地,如果别人不理解那些思想,即便知道那些简洁的方案,也很可能回答不好我的问题。所以,我的教训是当未到掌握聪明方法的时机时,不要强求,不是所有为了寻找好的解决方案而上网搜索花费的时间都是值得的。
笨方法思维并非是要专门思考需要手动处理较多的方法,而是‘在工作中可以不依赖资料帮助,遇到问题时可以独立快速地找到解决方案,使得工作的流畅度不受影响’的一种思维方式,它的确容易在条件或知识受限的情况下使用一些看似较笨的方法。有段时间我是一个特别喜欢使用新工具,新方法的人,看到别人还在使用某些旧工具旧方法时不免惊讶,还像别人推荐新工具和方法。现在想想,真是可笑,我只看到别人工具和方法的落后,却看不到别人高效完成工作背后的原因。好的工具方法可以提高单位时间的效率,笨方法思维也许才是保证流畅的工作节奏的原因。新工具方法的使用不过是工作中顺其自然的事。