一直说要好好学习,总结知识什么的。一直觉得没有时间。周一终于提交了论文盲审。决定从今天每周都总结一次自己的所学。希望自己能坚持。
任务描述:
一个医学系的同学要分析一个叫TCGA的数据库,每个实验文件是txt,格式如下:
hsa-miR-1228* 5.185500096 hsa-miR-1229 5.754380131
hsa-miR-1231 4.542420238 hsa-miR-1233 5.148618769
hsa-miR-1234 5.581203559
需要提取出几个指标的对应数据,指标需要她自己输入,根据文件名中的基因名称来排序生成一个excel表格,大约如下:
实现代码:
第一次写的不好,如果看了觉得可以改进请帮忙提出,谢谢。
https://github.com/LuyaoWang/...
实现过程:
这个任务我能想到的方案有:
1.配一个vs环境然后用C#做一个exe执行程序。但是对方有两台电脑,操作系统分别为mac和windows,所以就放弃了。
2.直接写shell脚本,可以处理txt和cvs。但是我不太确定,而且cvs还要转一层。
3.帮助对方配一个node环境,然后用node写个脚本运行一下。
因为我没用过node写脚本,所以就打算试一试,如果有更好的方案可以后续讨论。
1.安装nodejs
如果是帮不会代码的人装环境最好是直接去node官网下个对应版本就了了。不然折腾起来麻烦,地址如下:
https://nodejs.org/en/download/
如果涉及后续的开发,建议先下载nvm(node version manager),再装node。
安装nvm
在终端运行以下语句,里面的版本号看一下:
curl -o https://raw.githubusercontent.com/creationix/nvm/v0.25.2/install.sh | bash
我帮同学配的时候一直报错,说profile not found. Tried (as defined in $PROFILE),所以建议如果没有这个文件的话,先用以下语句建一个文件以后再运行
touch ~/.bash_profile
如果装完输入nvm还是找不到就把以下文字输入.bash_profile,出错提示里面也有的。
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
安装node
执行nvm install + 版本号,例如以下语句可以安装node7.几的版本(好像在墙内只能找到3.3.1以前的版本)
nvm install 7
使用nvm ls可以查看现有的node版本,nvm use 7 可以支持模糊切换。
安装依赖库
在node中已经包含了npm,node project manager吧。所以,我写了一个package.json文件,说明了这个脚本需要依赖的excel库,用npm install来自动安装。
2.node中读取txt
在我现在的理解下,我觉得node只是一个平台,里面有很多的api和库可以用来调用,真正开发的语言还是JavaScript,之后如果有更多理解会修改。所以我就查了一下node已经集合了一个名为fs的库用于处理txt。
主要用到两个api,readfile用来读文件,readdir用于读文件夹。
api文档地址:
https://nodejs.org/api/fs.htm...
建立一个文件app.js,然后把一下代码复制进去,在命令行输入node app.js就可以得到读取的txt文件内容了。
var fs = require("fs");
fs.readFile("txt文件地址", "utf-8", function(error, config) {
if (error) {
console.log(error);
console.log("config文件读入出错");
}
console.log(config.toString());
}
3.node中的正则表达式提取文字
这个需要用户输入提取的那个数据名词,然后我把数据名词后面的数字提取出来。这个交互,我使用的是让她填写一个config.txt,然后我解析一下提取出名词,按照正则表达式来匹配,一个名词一重循环(这里可以考虑排序名词,二分查找改进效率)。
正则匹配函数match()
原型:stringObj.match(regExp)
可以有两种使用方式,一种是写死匹配stringObj.match(/ddd/),一种是传入一个string,然后生成一个RegExp变量,如下:
var itemName = [];
itemName[0] = "hsa-miR-424";
var itemReg = [];
itemReg[0] = new RegExp(itemName[0]);\\itemName存有名词
data.match(itemReg[0]);
具体参看mdn里面有正则表达的详细过滤规则:
https://developer.mozilla.org...
4.node中导出excel
这个我主要参考了small2写的node.js读写excel文件。引入了库excel-export用于导出excel。基本上就是改了一下他的exports.write函数,加入了我需要导入的逻辑,因为我的首行各单元格内容是用户输入的,所以就是还要复制新的caption。并且有的时候需要合并另一个excel里面的cd274的值。
conf是所有需要导入excel的配置和数据。先把这个conf里面的所有数值填写好。包括conf.name就是工作表名称,conf.cols中存放首行单元格信息。conf.rows就是之后每一行的信息。
然后调用var result = excelPort.execute(conf),得到用于写入的二进制数据。
最后调用fs.writeFile(filePath, result, 'binary', call_back)写入excel。
另外有个问题,我发现type如果是number的时候我的excel打不开,不知道为什么。
var excelPort = require('excel-export');
exports.write = function(req, res) {
// console.log(itemName);
var conf = {};
conf.name = "mysheet";
conf.cols = [
{caption: 'gene_id', type: 'string', width: 40}
];
for (let i = 0; i < itemNum; i++) {
if (isCD274.match(/y/)) {
conf.cols[i + 2] = {caption: '', type: 'string', width: 40};
conf.cols[i + 2].caption = itemName[i];
} else {
conf.cols[i + 1] = {caption: '', type: 'string', width: 40};
conf.cols[i + 1].caption = itemName[i];
}
}
if (isCD274.match(/y/)) {
conf.cols[1] = {caption: 'cd274', type: 'string', width: 40};
}
conf.rows = req;
var result = excelPort.execute(conf);
var filePath = "./result.xlsx";
fs.writeFile(filePath, result, 'binary', function(err) {
if (err) {
console.log(err);
}
console.log("success!");
});
};
官方文档在此,但是例子用了express,我就没仔细看。
https://www.npmjs.com/package...
总结
第一次正经的自己装了一个node,然后花了一天时间实现了这个功能,还是很开心的。但是由于后来没什么耐心了,各种实现应该不太符合规范。等学习一段时间我再来改进。
这应该是我第一次用js做了脚本操作,之前基本就是最简单的dom操作。我的思维还是停留在c++的那种同步模式,本来想直接用同步机制,但是这样用js的好处就体会不到了。作用域的问题也特别乱,我感觉我一直在不停的把变量嵌套进回调函数。回调嵌套回调,我只知道如何输入一个数据到函数里,不知道怎么输出,只能无限循环进去,我看了一下express可以有req和res的交互,但是不想给一个这么小的例子加太多东西,所以就先这样。我觉得js本身应该解决了这个问题,只是我还没学到,下周研究一下这个问题,把作用域搞搞清楚。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。