【问题标题】:Keep rows with max value of a specific column保留具有特定列最大值的行
【发布时间】:2017-12-27 20:24:43
【问题描述】:

我是 Python 新手,我想做以下事情。我有一个包含标题行和 4 列的 csv 文件(input.csv)。该 csv 文件的一部分如下所示:

gene-name p-value stepup(p-value) fold-change
IFIT1 6.79175E-005 0.0874312 96.0464
IFITM1 0.00304362 0.290752 86.3192
IFIT1 0.000439152 0.145488 81.499
IFIT3 5.87135E-005 0.0838258 77.1737
RSAD2 6.7615E-006 0.0685623 141.898
RSAD2 3.98875E-005 0.0760279 136.772
IFITM1  0.00176673 0.230063 72.0445

我想只保留 fold-change 值最高的行,并删除所有其他包含相同基因名称但 fold-change 值较低的行。例如,在这种情况下,我需要以下格式的 csv 输出文件:

gene-name p-value stepup(p-value) fold-change
IFIT1 6.79175E-005 0.0874312 96.0464
IFITM1 0.00304362 0.290752 86.3192
RSAD2 6.7615E-006 0.0685623 141.898   
IFIT3 5.87135E-005 0.0838258 77.1737

如果您为我提供此问题的解决方案,我将不胜感激。
非常感谢。

【问题讨论】:

  • 你尝试了吗?发布您的代码....
  • 我尝试先按名称排序,然后使用 df.sort 保留基因的第一个最高倍数变化值,但没有成功。

标签: python arrays csv sorting


【解决方案1】:

愚蠢的解决方案:遍历文件中的每一行,进行手动比较。假设:

  • 每列由一个空格分隔
  • 结果行数应能放入内存,因为我们必须在将结果刷新到文件之前完成整个搜索和比较
  • 没有预排序,因此它的缩放(速度)很差,因为它会在每个输入行上执行完整的结果列表。
  • 如果某个基因后来以某种方式具有相同的倍数变化,您希望保留您看到的第一行。

::

fi = open('inputfile.csv','r') # read

header = fi.readline() 
# capture the header line ("gene-name p-value stepup(p-value) fold-change")    

out_a = [] # we will store the results in here

for line in fi: # we can read a line this way too
    temp_a = line.strip('\r\n').split(' ') 
    # strip the newlines, split the line into an array

    try:
        pos = [gene[0] for gene in out_a].index(temp_a[0])
        # try to see if the gene is already been seen before
        # [0] is the first column (gene-name)
        # return the position in out_a where the existing gene is
    except ValueError: # python throws this if a value is not found
        out_a.append(temp_a)
        # add it to the list initially
    else: # we found an existing gene
        if float(temp_a[3]) > float(out_a[pos][3]):
            # new line has higher fold-change (column 4)
            out_a[pos] = temp_a
            # so we replace

fi.close() # we're done with our input file
fo = open('outfile.csv','w') # prepare to write to output
fo.write(header) # don't forget about our header
for result in out_a:
    # iterate through out_a and write each line to fo
    fo.write(' '.join(result) + '\n')
    # result is a list [XXXX,...,1234]
    # we ' '.join(result) to turn it back into a line
    # don't forget the '\n' which makes each result on a line

fo.close()

这样做的一个优点是它保留了输入文件中基因的第一次遇到顺序。

【讨论】:

  • 不幸的是我收到错误:temp_a[0].append(temp_a) AttributeError: 'str' object has no attribute 'append' 为什么我们会收到这个错误@cowbert?
  • 重新加载页面,这是由于打字错误。
  • 很遗憾我收到一个新错误:if float(temp_a[3]) > float(out_a[pos][3]): IndexError: list index out of range 我们该如何解决?跨度>
  • 我不知道,我只是编辑了代码,它适用于您原始问题中的情况。您的输入文件是否缺少某个字段?
【解决方案2】:

尝试使用熊猫:

import pandas as pd

df = pd.read_csv('YOUR_PATH_HERE')

print(df.loc[(df['gene-name'] != df.loc[(df['fold-change'] == df['fold-change'].max())]['gene-name'].tolist()[0])])

代码很长,因为我选择了一行代码,但是代码做的是这个。我抓住最高fold-changegene-name,然后我使用!= 运算符说,“抓住我刚才计算的gene-namegene-name 不同的所有内容。

分解:

# gets the max value in fold-change
max_value = df['fold-change'].max()

# gets the gene name of that max value
gene_name_max = df.loc[df['fold-change'] == max_value]['gene-name']

# reassigning so you see the progression of grabbing the name
gene_name_max = gene_name_max.values[0]

# the final output
df.loc[(df['gene-name'] != gene_name_max)]

输出:

gene-name   p-value stepup(p-value) fold-change
0   IFIT1   0.000068    0.087431    96.0464
1   IFITM1  0.003044    0.290752    86.3192
2   IFIT1   0.000439    0.145488    81.4990
3   IFIT3   0.000059    0.083826    77.1737
6   IFITM1  0.001767    0.230063    72.0445

编辑:

要获得预期的输出,请使用groupby:

import pandas as pd

df = pd.read_csv('YOUR_PATH_HERE')
df.groupby(['gene-name'], sort=False)['fold-change'].max()

# output below
gene-name
IFIT1      96.0464
IFITM1     86.3192
IFIT3      77.1737
RSAD2     141.8980

【讨论】:

  • 很抱歉,但这不是我想要的。我需要在每一行中具有最高倍数变化值的不同基因名称。您的脚本不会删除所有具有相同基因名称和较低倍数变化值的行。是清楚还是您需要更多信息?
  • 有点困惑...您需要每个基因名称的最大值吗?
  • @ManolisSemidalas 根据您的预期输出进行了更新。
  • 那么您能否使用新的 groupby 命令上传完整的脚本,因为我不清楚命令的顺序?谢谢。
  • @ManolisSemidalas,已更新。让我知道这是否有帮助。 (你可能需要在最后一行代码附近调用print()
猜你喜欢
  • 1970-01-01
  • 2020-03-30
  • 1970-01-01
  • 2021-04-29
  • 2022-09-22
  • 2014-03-29
  • 2020-05-25
  • 2017-04-13
相关资源
最近更新 更多