行之间的条件数学运算

3

在收到反对票后重新发布,我试着回去尝试了一些东西,但我想还没有达到目标。

带有此类数据的文件:

name    count   count1  count3  add1    add2
jack    70  55  31  100174766   100170715
jack    45  656 48  100174766   100174052
john    41  22  89  102268764   102267805
john    47  31  63  102268764   102267908
david   10  56  78  103361093   103368592

我需要检查两个条件并进行一项数学运算: A)哪些行/列在add1中具有重复的值(始终等于2) B)如果它们等于2,则哪一行/列在add2中具有更大的值

以杰克为例:

jack    70  55  31  100174766   100170715
jack    45  656 48  100174766   100174052

Jack有两个add1 == 2(出现两次),而100174052更大,因此:

row1 = jack 45  656 48  100174766   100174052
row2 = jack 70  55  31  100174766   100170715

数学:

对于两行之间的每个单元格,使用以下公式进行计算:row1 /(row1+row2)

输出结果(针对Jack):

jack    0.391304348 0.922644163 0.607594937 100174766   100174052

最终期望的输出结果

name    count   count1  count3  add1    add2
jack    0.391304348 0.922644163 0.607594937 100174766   100174052
john    0.534090909 0.58490566  0.414473684 102268764   102267908

目前的代码:

我知道我还没有考虑哪一个add2更大,不确定在哪里以及如何处理它。

info = []
with open('file.tsv', 'r') as j:
    for i,line in enumerate(j):
        lines = line.strip().split('\t')
        info.append(lines)

uniq = {}
for index,row in enumerate(info, start =1):
    if row.count(row[4]) == 2:
       key = row[4] + ':' + row[5]
    if key not in uniq:
        uniq[key] = row[1:3]

for k, v in sorted(uniq.iteritems()):
    row1 = k,v
    row2 = k,v
    print 'row1: ', row1[0], '\n', 'row2: ',row2[0]

我看到的只有:

row1:  100174766:100170715 
row2:  100174766:100170715
row1:  100174766:100174052 
row2:  100174766:100174052

替代

row1:  100174766:100170715
row2:  100174766:100174052

add1 中是否还有其他值与“Jack”相同的值? - Patrick Artner
add1 中,不能有一个与同值的插孔。 - novicebioinforesearcher
2个回答

1
(dat.sort_values('add2',ascending=[False]).groupby(['name','add1']).aggregate(lambda x: (x.iloc[0]/sum(x))))

                    count    count1    count3      add2
name  add1                                             
david 103361093  1.000000  1.000000  1.000000  1.000000
jack  100174766  0.391304  0.922644  0.607595  0.500008
john  102268764  0.534091  0.584906  0.414474  0.500000

嗨Onyambu,感谢你的答案,这是否可以使用纯Python完成?只是好奇并正在学习基础知识。 - novicebioinforesearcher
@初学生物信息研究者 你说的“纯Python”是什么意思?还是你指的是R语言? - Onyambu
我的意思是使用pandas编写Python代码,你的答案也可以。 - novicebioinforesearcher

1

任何pandas可以做的事情,纯Python都可以完成 - 只需要更多的代码:

要将其作为完整的minimal verifyable complete example运行在https://pyfiddle.io内,您需要创建该文件:

# create file
with open("d.txt","w") as f:
    f.write("""name    count   count1  count3  add1    add2
jack    70  55  31  100174766   100170715
jack    45  656 48  100174766   100174052
john    41  22  89  102268764   102267805
john    47  31  63  102268764   102267908
david   10  56  78  103361093   103368592""")

那么,首先我定义一些辅助函数:
def printMe(gg):
    """Pretty prints a dictionary"""
    print ""
    for k in gg:
        print k, "\t:  ", gg[k]

def spaceEm(s):
    """Returns a string of input s with 2 spaces prepended"""
    return "  {}".format(s)

开始读取和计算您的值:

data = {}
with open("d.txt","r") as f:
    headers = f.readline().split() # store header line for later
    for line in f:
        if line.strip(): # just a guard against empty lines
            # name, *splitted = line.split() # python 3.x, you specced 2.7
            tmp = line.split()
            name = tmp[0]
            splitted = tmp[1:]
            nums = list(map(float,splitted))
            data.setdefault((name,nums[3]),[]).append(nums)
printMe(data)

# sort data
for nameAdd1 in data:
    # name     :  count   count1  count3  add1    add2 
    data[nameAdd1].sort(key = lambda x: -x[4]) # - "trick" to sort descending, you 
                                               # could use reverse=True instead 
printMe(data)


# calculate stuff and store in result
result = {}
for nameAdd1 in data:
    try:
        values = zip(*data[nameAdd1])

        # this results in value error if you can not decompose in r1,r2
        result[nameAdd1] = [r1 / (r1+r2) for r1,r2 in values]

    except ValueError:
        # this catches the case of only 1 value for a person 
        result[nameAdd1] = data[nameAdd1][0]
printMe(result)


# store as resultfile (will be overwritten each time)
with open("d2.txt","w") as f:
    # header
    f.write(headers[0])
    for h in headers[1:]:
        f.write(spaceEm(h))
    f.write("\n")

    # data
    for key in result:
        f.write(key[0]) # name
        for t in map(spaceEm,result[key]):
            f.write(t) # numbers
        f.write("\n")

输出:

# read from file
('jack', 100174766.0)   :   [[70.0, 55.0, 31.0, 100174766.0, 100170715.0], [45.0, 656.0, 48.0, 100174766.0, 100174052.0]]
('david', 103361093.0)  :   [[10.0, 56.0, 78.0, 103361093.0, 103368592.0]]
('john', 102268764.0)   :   [[41.0, 22.0, 89.0, 102268764.0, 102267805.0], [47.0, 31.0, 63.0, 102268764.0, 102267908.0]]

# sorted by add1
('jack', 100174766.0)   :   [[45.0, 656.0, 48.0, 100174766.0, 100174052.0], [70.0, 55.0, 31.0, 100174766.0, 100170715.0]]
('david', 103361093.0)  :   [[10.0, 56.0, 78.0, 103361093.0, 103368592.0]]
('john', 102268764.0)   :   [[47.0, 31.0, 63.0, 102268764.0, 102267908.0], [41.0, 22.0, 89.0, 102268764.0, 102267805.0]]

# result of calculations
('jack', 100174766.0)   :   [0.391304347826087, 0.9226441631504922, 0.6075949367088608, 0.5, 0.5000083281436545]
('david', 103361093.0)  :   [10.0, 56.0, 78.0, 103361093.0, 103368592.0]
('john', 102268764.0)   :   [0.5340909090909091, 0.5849056603773585, 0.4144736842105263, 0.5, 0.5000002517897694]

输入文件:

name    count   count1  count3  add1    add2
jack    70  55  31  100174766   100170715
jack    45  656 48  100174766   100174052
john    41  22  89  102268764   102267805
john    47  31  63  102268764   102267908
david   10  56  78  103361093   103368592

输出文件:

name  count  count1  count3  add1  add2
jack  0.391304347826087  0.9226441631504922  0.6075949367088608  0.5  0.5000083281436545
john  0.5340909090909091  0.5849056603773585  0.4144736842105263  0.5  0.5000002517897694
david  10.0  56.0  78.0  103361093.0  103368592.0

免责声明:我最初使用3.x编码,后来在http://pyfiddle.io上修复为2.7版本,可能存在一些“不必要”的中间变量以使其正常工作...

这个很完美,你还有它的py3版本吗?我应该使用py3,因为py27正在逐渐淡出。 - novicebioinforesearcher
我之前不知道 https://pyfiddle.io,这对我来说很有帮助,可以在那里提问。 - novicebioinforesearcher
1
@novicebioinforesearcher,这个 Python3 代码使用了 name, *splitted = line.split() 解构语法(代码中仍然注释掉)。你需要将 print 语句改为使用 (....),因为在 Python 3.x 中 print 是一个函数。这是主要的修改内容。在这段代码中使用的 mapzip 不需要更改(它们只迭代一次),所以不需要在它们周围加上列表(它们在2.7中返回列表,在3.x中返回生成器 - 所以如果你想要多次使用它们,就需要将它们放在列表中)。 - Patrick Artner
1
@novicebioinforesearcher 关于pyfiddle.io-. 请确保正确切换2.7/3.6并熟悉其特点(例如,您需要首先在代码内部创建文件才能对文件进行操作),关于参数传递和input()值传递。您需要首先将东西放入输入字段中。如果可以选择2.7或3.6, 我会使用3.6-2.7即将在2020年退出市场,并且几乎所有的事情都已经移植,所以没有必要停留在2.x-ish上面。 - Patrick Artner
啊,我明白了,我想我没有理解这部分内容 所以不需要在它们周围使用列表(它们在2.7中返回列表,在3.x中返回生成器),请在答案中注释掉 - novicebioinforesearcher
1
@novicebioinforesearcher 在这个问题中了解到一些内置函数在2.x和3.x版本中使用上的差异。 - Patrick Artner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接