Chinaunix
标题:
python 如何按列合并两个文件?
[打印本页]
作者:
小风0000
时间:
2016-04-29 02:34
标题:
python 如何按列合并两个文件?
数据如下:
dat1='''
a 11
b 12
c 13
'''
dat2='''
d 1.3
a 2.4
b 4.3
v 2.2
c 3.4
'''
如何按第1列合并数据,得到以下结果:
a 11 2.4
b 12 4.3
c 13 3.4
求指导!!!
本来我的想法是,把数据都存成二维数组,然后循环dat1的第1列,判断dat2有没有,有的合在一块。
可是找了很久,卡在怎么取dat2的第1列,怎么能一下子取出某列呢?
网上看有人推荐Pandas 正在学习……
作者:
mswsg
时间:
2016-04-29 09:40
本帖最后由 mswsg 于 2016-04-29 10:40 编辑
先占楼,你起得这么早呢
python test.py --input1 dat1.txt --input2 dat2.txt > 2.out.txt
复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'shengwei ma'
__author_email__ = 'shengweima@icloud.com'
import sys
import getopt
input_file1 = ""
input_file2 = ""
try:
opts, args = getopt.getopt(sys.argv[1:], "h", ["input1=", "input2="])
except getopt.GetoptError as err:
print(str(err))
for op, value in opts:
if op == "--input1":
input_file1 = value
elif op == "--input2":
input_file2 = value
elif op == "-h":
print("python get_value_according_first_column.py --input1 dat1 --input2 dat2 > out.txt")
sys.exit()
# 以上可忽略,定义shell中接受的参数及数据
f1 = open(input_file1, 'r')
f2 = open(input_file2, 'r')
lines1 = f1.readlines() # 将整个文件读作一个列表,可以添加 print lines1 查看,这里一行表示里边的一个元素(字符串),如lines1[0],则表示第一行
lines2 = f2.readlines() # 将整个文件读作一个列表,可以添加 print lines2 查看,第一行第一列,lines2[0][0]
for line1 in lines1: # 遍历列表lines1中的每个元素,及遍历读取文件1的每一行
line1 = line1.strip().split() # 这里的一行就是一个字符串,使用字符串的strip方法,去掉行尾换行符,使用split分割字符串成列表
for line2 in lines2:
line2 = line2.strip().split() # 同样 遍历文件2中每一行
if line1[0] in line2: # line1[0] (注意是line 不是lines) 表示某一行的第一列,即查询某行第一列是否在文件2中,如果在
line1.extend(line2[1:]) # 在的话,则将 文件2中的第二列以后的部分添加到第一行的后边
print ' '.join(line1) # 将列表 line1 转换成字符串打印
f1.close() # 关闭文件
f2.close() # 关闭文件
复制代码
作者:
小风0000
时间:
2016-04-29 11:09
回复
2#
mswsg
谢谢,前面的没看明白,后面的看明白了。感觉python代码好长啊,我以前学R的,用R的话一句话就搞定了。不过R没有python运算速度快,问下python的哲学是不是都得用循环?而没有什么高级函数,都要自己造轮子?
作者:
Linux_manne
时间:
2016-04-29 11:25
本帖最后由 Linux_manne 于 2016-04-29 11:34 编辑
感觉长 那就简化下
f1 = open('1.txt', 'r').readlines()
f2 = open('2.txt', 'r').readlines()
print [ (l1.split()[0], l1.split()[1], l2.split()[1]) for l1 in f1 for l2 in f2 if l1.split()[0] == l2.split()[0] ]
复制代码
########### 不嵌套tuple 的############
print [ "{0[0]} {0[1]} {1[1]}".format(l1.split(), l2.split()) for l1 in f1 for l2 in f2 if l1.split()[0] == l2.split()[0] ]
复制代码
作者:
Linux_manne
时间:
2016-04-29 11:29
回复
3#
小风0000
python 有很多pythonic 的写法... 可惜 这个要很有经验的人才 写的出来, 上述那种简洁的写法 其实还可以优化..
作者:
mswsg
时间:
2016-04-29 11:29
本帖最后由 mswsg 于 2016-04-29 11:34 编辑
这个列表解析,如果能理解,这个好。
是不是自己造轮子,我还真不知道,对于初学者应用基本python知识造轮子其实还挺好的。
有没有其他第三方模块,暂时未知
回复
4#
Linux_manne
作者:
Linux_manne
时间:
2016-04-29 11:40
回复
6#
mswsg
你应该回复lz 而不是我.......
作者:
小风0000
时间:
2016-04-29 11:51
谢谢大家,还是不好高骛远了,先把基础打好,能得到结果才是硬道理!
作者:
过过招
时间:
2016-04-29 11:57
from os import linesep
f1 = open('/root/1.txt')
f2 = open('/root/2.txt')
f3 = open('/root/3.txt', 'w')
lines1 = f1.readlines()
lines2 = f2.readlines()
for line1 in lines1:
k = line1.split()[0]
for line2 in lines2:
if line2.split()[0] == k:
line3 = line1.replace(linesep, '') + " " + str(line2.split()[1]) + linesep
f3.write(line3)
f1.close()
f2.close()
f3.close()
作者:
Hadron74
时间:
2016-04-29 12:11
回复
1#
小风0000
这个最好用字典,而不用列表。速度会大不一样的。不信你用个大数据集>10000, 试试。
代码如下:
with open("1.txt") as IN1, open("2.txt") as IN2:
f1 = { k:v for k,v in [l1.split() for l1 in IN1 ]}
f2 = { k:v for k, v in [l2.split() for l2 in IN2]}
print [ (k,f1[k],f2[k] ) for k in f2 if k in f1 ]
复制代码
[('a', '2.4', '11'), ('c', '3.4', '13'), ('b', '4.3', '12')]
复制代码
作者:
q1208c
时间:
2016-04-29 12:30
回复
10#
Hadron74
但字典恐怕内存不够用吧?如果数据真的很多的话。
作者:
Hadron74
时间:
2016-04-29 12:47
回复
11#
q1208c
小数据两个问题都不大,这是折中的方案,从算法角度说用二次列表时o(n**2),而字典(哈希)时o(n);
如果数据再大列表也不行,需要用迭代器或是文件逐行读取排序的方式了。
作者:
mswsg
时间:
2016-04-29 12:56
学习!已关注微博
回复
10#
Hadron74
作者:
Hadron74
时间:
2016-04-29 13:01
回复
13#
mswsg
谢谢关注!Python生物信息, 这个可能你会感兴趣:
http://blog.sciencenet.cn/blog-565112-510336.html
作者:
mswsg
时间:
2016-04-29 13:05
本帖最后由 mswsg 于 2016-04-29 13:06 编辑
哈哈,我也是科学网用户,原来已经是好友了
回复
14#
Hadron74
作者:
mswsg
时间:
2016-04-29 13:14
是不是只是打印了文件1和文件2第一列都有的,文件1有,但是文件2没有的呢?
a 11
b 12
c 13
dd 14
复制代码
d 1.3
a 2.4
b 4.3
v 2.2
c 3.4
复制代码
a 11 2.4
b 12 4.3
c 13 3.4
dd 14
复制代码
回复
4#
Linux_manne
作者:
Linux_manne
时间:
2016-04-29 13:16
回复
16#
mswsg
是
作者:
Hadron74
时间:
2016-04-29 16:42
本帖最后由 Hadron74 于 2016-04-29 16:49 编辑
回复
11#
q1208c
快五一了,没事。再写一个处理巨大文件的脚本.
其实这个问题没有必要用Python,用Shell就能完成,bash 一行,有兴趣的朋友可以玩一下。
join <(sort 1.txt) <(sort 2.txt)
复制代码
a 2.4 11
b 4.3 12
c 3.4 13
复制代码
祝大家五一快乐!
作者:
q1208c
时间:
2016-05-05 00:55
回复
12#
Hadron74
如果真的很大的文件, 估计得考虑 merge-sort 算法了。
这是 sort命令用的算法。
我不是学计算机的, 不知道是不是还有更好的算法。
作者:
Hadron74
时间:
2016-05-05 08:50
本帖最后由 Hadron74 于 2016-05-05 08:55 编辑
回复
19#
q1208c
是这样。
作者:
小风0000
时间:
2016-05-11 03:19
学习了,谢谢大家
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2