Python文件预处理(将列从离散值范围转换为连续值范围。)

时间:2014-04-13 00:38:43

标签: python algorithm sorting

我有一个表格的数据集:

user_id::item_id1::rating::timestamp
user_id::item_id2::rating::timestamp
user_id::item_id3::rating::timestamp
user_id::item_id4::rating::timestamp

我需要item_ids(按排序顺序有n个不同的项ID。后续行可以具有相同的项ID或不同但保证可以对其进行排序)从1到n是连续的,它们当前的范围从1到1 ķ

表示k>> n

我有以下代码,但它不是很正确并且已经使用了几个小时所以非常感谢有关这方面的任何帮助,或者如果有更简单的方法在python中执行此操作我会真的也赞赏有关这方面的指导。

我目前有以下代码:

def reOrderItemIds(inputFile,outputFile):
        #This is a list in the range of 1 to 10681.
        itemIdsRange = set(range(1,10682))
        #currKey = 1
        currKey = itemIdsRange.pop()
        lastContiguousKey=1
        #currKey+1
        contiguousKey=itemIdsRange.pop()
        f = open(inputFile)
        g = open(outputFile,"w")
        oldKeyToNewKeyMap = dict()
        for line in f:
                if int(line.split(":")[1]) == currKey and int(line.split(":")[1])==lastContiguousKey:
                        g.write(line)
                elif int(line.split(":")[1])!=currKey and int(line.split(":")[1])!=contiguousKey:
                        oldKeyToNewKeyMap[line.split(":")[1]]=contiguousKey
                        lastContiguousKey=contiguousKey
                        #update current key to the value of the current key.
                        currKey=int(line.split(":")[1])
                        contiguousKey=itemIdsRange.pop()
                        g.write(line.split(":")[0]+":"+str(lastContiguousKey)+":"+line.split(":")[2]+":"+line.split(":")[3])
                elif int(line.split(":")[1])==currKey and int(line.split(":")[1])!=contiguousKey:
                        g.write(line.split(":")[0]+":"+str(lastContiguousKey)+":"+line.split(":")[2]+":"+line.split(":")[3])

                elif int(line.split(":")[1])!=currKey and int(line.split(":")[1])==contiguousKey:
                        currKey = int(line.split(":")[1])
                        lastContiguousKey=contiguousKey
                        oldKeyToNewKeyMap[line.split(":")[1]] = lastContiguousKey
                        contiguousKey=itemIdsRange.pop()
                        g.write(line.split(":")[0]+":"+str(lastContiguousKey)+":"+line.split(":")[2]+":"+line.split(":")[3])
        f.close()
        g.close()

示例:

1::1::3::100
10::1::5::104
20::2::3::110
1::5::2::104

我要求输出格式为:

1::1::3::100
10::1::5::104
20::2::3::110
1::3::2::104

所以只有item_ids列发生了变化,其他一切都保持不变。

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

因为您的数据已按item_id排序 - 您可以使用itertools.groupby()来简化解决方案的工作。

from operator import itemgetter
from itertools import groupby

item_id = itemgetter(1)
def reOrderItemIds(inputFile,outputFile):
    n = 1
    with open(inputFile)as infile, open(outputFile,"w") as outfile:
        dataset = (line.split('::') for line in infile)
        for key, group in groupby(dataset, item_id):
            for line in group:
                line[1] = str(n)
                outfile.write('::'.join(line))
            n += 1

答案 1 :(得分:0)

我很抱歉第一次严重误读了您的问题,假设data是一个包含

的文件
1::1::3::100
10::1::5::104
20::2::3::110
30::5::3::121
40::9::7::118
50::10::2::104

(如果您的数据不能全部转换为整数,则可以修改它。)

>>> with open('data', 'r') as datafile:
...   dataset = datafile.read().splitlines()
...
>>> ids = {0}
>>> for i, line in enumerate(dataset):
...   data = list(map(int, line.split('::')))
...   if data[1] not in ids:
...     data[1] = max(ids) + 1
...     ids.add(data[1])
...   dataset[i] = '::'.join((str(d) for d in data))
...
>>> print('\n'.join(dataset))
1::1::3::100
10::1::5::104
20::2::3::110
30::3::3::121
40::4::7::118
50::5::2::104

同样,如果您的数据集很大,可以设计出更快的解决方案。