在数组

时间:2017-03-01 04:16:36

标签: python algorithm numpy grouping slice

我正在python中编写一个程序,需要在文本文件中对四列数据进行排序,并在第一列中为每组相同数字返回第三列中编号最大的行的四个数字。

例如:

我需要:

1.0     19.3    15.5    0.1
1.0     25.0    25.0    0.1
2.0     4.8     3.1     0.1
2.0     7.1     6.4     0.1
2.0     8.6     9.7     0.1
2.0     11.0    14.2    0.1
2.0     13.5    19.0    0.1
2.0     16.0    22.1    0.1
2.0     19.3    22.7    0.1
2.0     25.0    21.7    0.1
3.0     2.5     2.7     0.1
3.0     3.5     4.8     0.1
3.0     4.8     10.0    0.1
3.0     7.1     18.4    0.1
3.0     8.6     21.4    0.1
3.0     11.0    22.4    0.1
3.0     19.3    15.9    0.1
4.0     4.8     16.5    0.1
4.0     7.1     13.9    0.1
4.0     8.6     11.3    0.1
4.0     11.0    9.3     0.1
4.0     19.3    5.3     0.1
4.0     2.5     12.8    0.1
3.0     25.0    13.2    0.1

要返回:

1.0     19.3    15.5    0.1
2.0     19.3    22.7    0.1
3.0     11.0    22.4    0.1
4.0     4.8     16.5    0.1

这里返回行[1.0,19.3,15.5,0.1],因为15.5是任何行中最大的第三列值,其中1.0是第一个数字的所有行。对于第一列中的每组相同数字,该函数必须返回第三列中具有最大值的行。

我在python中实际做这件事很困难,因为循环遍历每一行并找到一个最大值,而不是每个'set'的第一列数。

有什么关于for循环我不知道哪些可以帮我这么做?

以下是我到目前为止的情况。

import numpy as np

C0,C1,C2,C3 = np.loadtxt("FILE.txt",dtype={'names': ('C0', 'C1', 'C2','C3'),'formats': ('f4', 'f4', 'f4','f4')},unpack=True,usecols=(0,1,2,3))

def FUNCTION(C_0,C_1,C_2,C_3):
    for i in range(len(C_1)):
        a = []
        a.append(C_0 [i])   
            for j in range(len(C_0)):
                if C_0[j] == C_0[i]:
                    a.append(C_0 [j])
        return a


print FUNCTION(C0,C1,C2,C3)

其中C0,C1,C2和C3是文本文件中的列,作为1-D数组加载。 现在我只是试图用相等的C0值隔离行的索引。

3 个答案:

答案 0 :(得分:0)

方法可以是使用dict,其中值是由第一列项键控的行。这样您就不必一次将整个文本文件加载到内存中。您可以逐行扫描并随时更新字典。

答案 1 :(得分:0)

由于第一排和第二排,我得到了一些复杂的...我相信25.0(2,3)是你的错误。

我的代码不是数学解决方案,但它可以起作用。

import collections

with open("INPUT.txt", "r") as datasheet:
    data = datasheet.read().splitlines()

dataset = collections.OrderedDict()

for dataitem in data:
    temp = dataitem.split("    ")
    # I just wrote this code, input and output was seperated by four spaces
    print(temp)
    if temp[0] in dataset.keys():
        if float(dataset[temp[0]][1]) < float(temp[2]):
            dataset[temp[0]] = [temp[1], temp[2], temp[3]]
    else:
        dataset[temp[0]] = [temp[1], temp[2], temp[3]]

# Some sort code here

with open("OUTPUT.txt", "w") as outputsheet:
    for datakey in dataset.keys():
        datavalue = dataset[datakey]
        outputsheet.write("%s    %s    %s    %s\n" % (datakey, datavalue[0], datavalue[1], datavalue[2]))

答案 2 :(得分:0)

使用Numpy和Lambda

使用具有一些lambda函数的dict的属性可以解决问题..

data = np.loadtxt("FILE.txt",dtype={'names': ('a', 'b', 'c','d'),'formats': ('f4', 'f4', 'f4','f4')},usecols=(0,1,2,3))

# ordering by columns 1 and 3
sorted_data = sorted(data, key=lambda x: (x[0],x[2]))

# dict comprehension mapping the value of first column to a row
# this will overwrite all previous entries as mapping is 1-to-1
ret = {d[0]: list(d) for d in sorted_data}.values()

或者,你可以把它变成一个(丑陋的)衬里......

ret = {
    d[0]: list(d)
    for d in sorted(np.loadtxt("FILE.txt",dtype={'names': ('a', 'b', 'c','d'),
                                                 'formats': ('f4', 'f4', 'f4','f4')},
                                          usecols=(0,1,2,3)),
                    key=lambda x: (x[0],x[2]))
}.values()

正如@Fallen指出的那样,这是一种效率低下的方法,因为您需要读取整个文件。但是,对于此示例中数据集非常小的目的,它是合理可接受的。

一次读一行

更有效的方法是一次读取一行。

import re

# Get the data
with open('data', 'r') as f:
    str_data = f.readlines()

# Convert to dict
d = {}
for s in str_data:
    data = [float(n) for n in re.split(r'\s+', s.strip())]

    if data[0] in d:
        if data[2] >= d[data[0]][2]:
            d[data[0]] = data
    else:
        d[data[0]] = data

print d.values()

这里需要注意的是,没有其他排序指标,所以如果您最初有1.0[1.0, 2.0, 3.0, 5.0],那么任何后续行1.0,其中第3列更大或等于3.0将被覆盖,例如[1.0, 1.0, 3.0, 1.0]