如何识别缺失的指数

时间:2019-05-14 23:49:53

标签: python python-3.x indexing

我有一个文本文件,其中包含数百万个索引点,这些索引点都被解释为字符串,并且用制表符分隔。但是,某些索引点可能会丢失。这是我的文本文件的示例:

var result = Speach.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
                   .Select(x => Regex.Replace(x.ToLower(), "[^a-zA-Z0-9-]", ""))
                   .GroupBy(x => x)
                   .ToDictionary(x => x.Key, x => x.Count());

Print(result.OrderByDescending(x => x.Value).ToList());

请注意,第4、6和8行丢失。我的目标是创建一个可以解析文本文件,识别可能缺少的索引点并返回包含所有缺少的索引点(如果有)或不返回任何内容的列表的函数。

我在Spyder IDE Windows10操作系统中使用Python 3.7。我对Python和Stackoverflow比较陌生。

这是我到目前为止所掌握的。这适用于ID 1缺少索引,但是如果缺少几个索引点,则失败。

错误从第一行else开始。我不确定如何使用for循环的索引(0、1、2、3 ...)跟踪文档(1、2、3、5 ...)中观察到的索引,因为随着时间的推移缺少索引点。

请注意,文本文档的前4行包含标头信息,我在解析过程中忽略了标头信息,这就是为什么data = f.readlines()[4:]

1       0       4         0d 07:00:37.0400009155273   
2       0       4         0d 07:00:37.0400009155273   
3       0       4         0d 07:00:37.0400009155273   
5       0       4         0d 07:00:37.0400009155273   
7       0       4         0d 07:00:37.0400009155273   
9       0       4         0d 07:00:37.0400009155273

...

感谢所有帮助!

4 个答案:

答案 0 :(得分:1)

您可以单独使用Python做到这一点:

with open(filename) as f:
    indices = [int(row.split('\t')[0]) for row in f.read().split('\n')[4:]]

missing_indices = [index 
                   for index in range(1, len(indices) + 1)
                   if index not in indices]

这会将您的数据转换为嵌套的list,其中每个外部list包含一行,每个内部list包含一个元素。由于我们只关心索引,因此我们得到第一个元素而忽略其他元素。

然后,由于索引按从1开始的运行顺序,我们构造了一个{<1>}跨越索引的 expected 范围,并获取存在于该范围但不存在于该范围内的索引文件。

假设索引是唯一的(这似乎是合理的),我们还可以使用 DYZ 的建议使用range

sets

missing_indices = set(range(1, len(indices) + 1) - set(indices) 也可以正常工作:

pandas

这将从您的数据中创建一个import pandas as pd df = pd.read_csv(filename, sep='\t').iloc[4:] range_index = pd.RangeIndex(1, len(df) + 1) print(range_index[~range_index.isin(df.iloc[:, 0])] DataFrame,并切断了前四行。遵循与其他答案相同的原理,它创建一个具有所有期望值的索引,并获取DataFrame第一列中不存在的子集。

答案 1 :(得分:1)

另一个答案为您提供了更好的整体解决方案,但是我只是想帮助您指导给定的正确方向,以便您了解如何改变自己的工作方式:

def check_sorted_file(fileName):
    missing_idx = []
    last_index = 0
    with open(fileName, 'r') as f:
        data = f.readlines()[4:]

    for line in data:
        idx = int(line.split()[0])
        if idx == last_index+1:
            pass
        else:
            missing_idx.extend(list(range(last_index+1, idx)))
        last_index = idx

    if missing_idx:
        print('\nThe following idicie(s) are missing: ')
        print(*missing_idx, sep=", ")
    else:
        print('\nAll indices are accounted for. ')
    return missing_idx

因此,无需使用枚举,我们将使用传入索引作为我们所在位置的指南。

要解决多个遗漏问题,我们使用range获取最后一个索引和当前索引之间的所有数字,并使用新的数字集扩展列表。

答案 2 :(得分:1)

由于行数很多,您可能希望以懒惰的方式执行此操作,而无需创建大列表或使用signal来测试每个值是否在百万行列表中。您可以混合使用一些itertools作为迭代器,并保存列表的末尾(如果您需要的话)。

基本上,您将intee做成两个迭代器以获取索引,用map剔除其中一个的值,然后压缩它们以检查是否存在差异:< / p>

next()

结果:

from itertools import chain, tee
lines = ["1       0       4         0d 07:00:37.0400009155273",
"2       0       4         0d 07:00:37.0400009155273",
"3       0       4         0d 07:00:37.0400009155273",
"5       0       4         0d 07:00:37.0400009155273",
"7       0       4         0d 07:00:37.0400009155273",
"9       0       4         0d 07:00:37.0400009155273"
]

#two iterators going over indexes 
i1, i2 = tee(map(lambda x: int(x.split()[0]), lines), 2)

# move one forward
next(i2) 

# chain.from_iterable will be an iterator producing missing indexes: 
list(chain.from_iterable(range(i+1, j) for i, j in zip(i1, i2) if j-i!=1))

答案 3 :(得分:0)

这是一个紧凑,健壮,基于集合的仅Python核心解决方案。读取文件,将每一行拆分为多个字段,将第一个字段转换为一个int,然后构建一组实际索引:

skip = 4 # Skip that many lines
with open(yourfile) as f:
    for _ in range(skip):
        next(f)
    actual = {int(line.split()[0]) for line in f}

创建一组预期的索引并取差值:

expected = set(range(min(actual), max(actual) + 1))
sorted(expected - actual)
#[4, 6, 8]

即使索引不是从1开始,该解决方案仍然有效。