csv 如何在python中根据索引值过滤列表?

7bsow1i6  于 10个月前  发布在  Python
关注(0)|答案(3)|浏览(91)

假设我有两个列表,记录每个人每天吃的苹果数量:
people ='George','George',' George','Dana',' John','John']
apples_eaten = [5,1,3,4,3,3]
在这个场景中,我们有来自乔治的3天数据、来自达纳的1天数据和来自约翰的2天数据。
我想知道是否有一个代码可以根据“people”列表过滤数据,这样我就可以用输出[5,1,3]拉取乔治的数据。
我想知道是否有一种方法可以更容易地做到这一点,如果我有这个数据在矩阵格式与每个数据集是一行,这样的索引是排队?我拉这些列表从一个csv文件,但我想知道如果我应该只是拉整个数据集从csv文件作为一个矩阵。
特别是寻找没有循环的代码,因为我可以很容易地用循环来编码,但我只是想避免它,因为我的数据集很大,我的代码中已经有一些循环,所以我试图使它尽可能高效。
编辑:我想最小化循环的原因是因为我有4000个“人”需要排序,假设数字为1-4000,我需要将这些人Map到大约11,000个数据点。
我想到的循环是这样的:

unique_list = [] # list of people with unique IDs numbered 1-4000 
people = [] # list of 11,000 repeated ID numbers matching up with data points
data = [] # list of 11,000 data points 

 for i in len(unique_list) 
   data_sorted = []
   ID = unique_list[i]
   for x in len(data) 
       if people[x] = ID 
           data_sorted.append(data[x]) 
       else

字符串
所以我想避免这样做的原因是因为我有大量的数据,这将永远需要,我只是不认为这是最有效的代码。让我知道你们的想法,谢谢!

mwg9r5ms

mwg9r5ms1#

“没有循环”在这里是一个荒谬的条件。当数据没有结构可以利用时,循环是不可避免的。唯一合理的方法是使用循环;循环的几个替代方案将不得不用额外的步骤来完成所有相同的工作,可能是以一种效率较低的方式。如果你没有看到循环,那是因为循环隐藏在为你循环的API后面。
除此之外,* 单一 * 查找的解决方案是zip上的listcomp:

people = ['George', 'George', 'George', 'Dana', 'John', 'John']

apples_eaten = [5, 1, 3, 4, 3, 3]

person_data = [cnt for person, cnt in zip(people, apples_eaten) if person == 'George']

字符串
就是这样。这里有一个循环。它是listcomp的一部分,CPython对它进行了大量优化。zip本身也针对这种情况进行了大量优化(当每次解压缩它产生的tuple时,它会重用 * 相同的 * tuple,因此不会发生分配)。它可以在任何大小的数据中一次查找单个人,但是您将为查找的每个人执行O(n)工作,因此如果您需要查找数据中的多个人或所有人,则无法很好地扩展。
如果您可能需要查找多个人,并且数据很少更改,您可以预先做一些工作,以使每个人的查找更便宜。最简单的解决方案是制作list s的dict,将每个人Map到其相关数据,例如:

from collections import defaultdict  # At top of file

person_to_eaten_count = defaultdict(list)

for person, cnt in zip(people, apples_eaten):
    person_to_eaten_count[person].append(cnt)

# Optionally convert back to plain `dict` to prevent future autovivification of keys
person_to_eaten_count = dict(person_to_eaten_count)


一旦你做了那个dict(成本并不比搜索单个人的数据高多少;构建dict的成本是O(n),只是常数因子略高),查找 * 任何 * 人的数据变得便宜得可笑; person_to_eaten_count['George']将通过O(1)工作获取George的数据,您也可以为任何其他人做同样的事情。

cunj1qz1

cunj1qz12#

如果你的人名总是连续且唯一的,你可以使用groupby函数从源列表中构建一个字典:

people = ['George', 'George', 'George', 'Dana', 'John', 'John']
apples_eaten = [5, 1, 3, 4, 3, 3]

from itertools import groupby
iPeople     = iter(people)
data_sorted = {p:g for p,(*g,) in
               groupby(apples_eaten,key=lambda _:next(iPeople))}

print(data_sorted)

{'George': [5, 1, 3], 'Dana': [4], 'John': [3, 3]}

字符串
如果名称不一定是连续的,您可以使用字典更新来按名称组织结果:

data_sorted = dict()
data_sorted.update( (p,data_sorted.get(p,[])+[a]) 
                    for p,a in zip(people,apples_eaten) )

print(data_sorted)

[('George', [5, 1, 3]), ('Dana', [4]), ('John', [3, 3])]

dgsult0t

dgsult0t3#

就像这样:

people = ['George', 'George', 'George', 'Dana', 'John', 'John']
apples_eaten = [5, 1, 3, 4, 3, 3]
dict1={}
i=0
for p in people:
    if p in dict1.keys():
        dict1[p].append(int(apples_eaten[i]))
    else:
        dict1[p]=list([])
        dict1[p].append(int(apples_eaten[i]))
    i+=1 
print(dict1)

字符串
产出:

{'George': [5, 1, 3], 'Dana': [4], 'John': [3, 3]}

相关问题