Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将csv.DictReader对象转换为非iter类型的数据,并按键合并值_Python_Csv_Dictionary_Itertools_Ordereddictionary - Fatal编程技术网

Python 将csv.DictReader对象转换为非iter类型的数据,并按键合并值

Python 将csv.DictReader对象转换为非iter类型的数据,并按键合并值,python,csv,dictionary,itertools,ordereddictionary,Python,Csv,Dictionary,Itertools,Ordereddictionary,在我的数据中: myData='''pos\tidx1\tval1\tidx2\tval2 11\t4\tC\t6\tA 15\t4\tA\t6\tT 23\t4\tT\t6\tT 28\t4\tA\t3\tG 34\t4\tG\t3\tC 41\t4\tC\t4\tT 51\t4\tC\t4\tC''' 我用标题作为键来读取此数据,csv.DictReader import csv import itertools input_file = csv.DictReader(io.String

在我的数据中:

myData='''pos\tidx1\tval1\tidx2\tval2
11\t4\tC\t6\tA
15\t4\tA\t6\tT
23\t4\tT\t6\tT
28\t4\tA\t3\tG
34\t4\tG\t3\tC
41\t4\tC\t4\tT
51\t4\tC\t4\tC'''
我用标题作为键来读取此数据,csv.DictReader

import csv
import itertools

input_file = csv.DictReader(io.StringIO(myData), delimiter = '\t')
# which produces an iterator

''' Now, I want to group this dictionary by idx2, where
idx2 values is the main key and other have values merged into list that have same keys'''

# This groupby method give me
file_blocks = itertools.groupby(input_file, key=lambda x: x['idx2'])

# I can print this as
for index, blocks in file_blocks:
    print(index, list(blocks))

6 [{'val2': 'A', 'val1': 'C', 'idx1': '4', 'pos': '11', 'idx2': '6'}, {'val2': 'T', 'val1': 'A', 'idx1': '4', 'pos': '15', 'idx2': '6'}, {'val2': 'T', 'val1': 'T', 'idx1': '4', 'pos': '23', 'idx2': '6'}]
3 [{'val2': 'G', 'val1': 'A', 'idx1': '4', 'pos': '28', 'idx2': '3'}, {'val2': 'C', 'val1': 'G', 'idx1': '4', 'pos': '34', 'idx2': '3'}]
4 [{'val2': 'T', 'val1': 'C', 'idx1': '4', 'pos': '41', 'idx2': '4'}, {'val2': 'C', 'val1': 'C', 'idx1': '4', 'pos': '51', 'idx2': '4'}]

But, since the output is exhausted I can't print, use it more than once to debug it.
所以,
问题#1:如何将其转换为非iter类型的数据

问题#2:如何进一步处理此groupby对象以将值合并到同一组/块中具有公用键的列表中

Something like orderedDict, defaultDict where the order of the way the data is read is preserved:

{'6': defaultdict(<class 'list'>, {'pos': [11, 15, 23], 'idx1': [4, 4, 4], 'val1': ['C', 'A', 'T'], 'idx2': [6, 6, 6], 'val2': ['A', 'T', 'T']})}
{'3': .....
{'4': .....
我尝试的另一件事是,如果我可以合并分组对象中的数据,请执行以下操作: 新的_groupBy={} 对于索引,文件中的块\u块: 打印(索引、列表(块)) 对于块中的x: 对于k,v在x中:
为new_groupBy做点什么,这样,对于您的第一个问题,您只需具体化一个列表:

In [9]: raw_data='''pos\tidx1\tval1\tidx2\tval2
    ...: 11\t4\tC\t6\tA
    ...: 15\t4\tA\t6\tT
    ...: 23\t4\tT\t6\tT
    ...: 28\t4\tA\t3\tG
    ...: 34\t4\tG\t3\tC
    ...: 41\t4\tC\t4\tT
    ...: 51\t4\tC\t4\tC'''

In [10]: data_stream = csv.DictReader(io.StringIO(raw_data), delimiter="\t")

In [11]: grouped = itertools.groupby(data_stream, key=lambda x:x['idx2'])

In [12]: data = [(k,list(g)) for k,g in grouped] # order is important, so use a list

In [13]: data
Out[13]:
[('6',
  [{'idx1': '4', 'idx2': '6', 'pos': '11', 'val1': 'C', 'val2': 'A'},
   {'idx1': '4', 'idx2': '6', 'pos': '15', 'val1': 'A', 'val2': 'T'},
   {'idx1': '4', 'idx2': '6', 'pos': '23', 'val1': 'T', 'val2': 'T'}]),
 ('3',
  [{'idx1': '4', 'idx2': '3', 'pos': '28', 'val1': 'A', 'val2': 'G'},
   {'idx1': '4', 'idx2': '3', 'pos': '34', 'val1': 'G', 'val2': 'C'}]),
 ('4',
  [{'idx1': '4', 'idx2': '4', 'pos': '41', 'val1': 'C', 'val2': 'T'},
   {'idx1': '4', 'idx2': '4', 'pos': '51', 'val1': 'C', 'val2': 'C'}])]
至于第二个问题,请尝试以下方法:

In [15]: import collections

In [16]: def accumulate(data):
    ...:     acc = collections.OrderedDict()
    ...:     for d in data:
    ...:         for k,v in d.items():
    ...:             acc.setdefault(k,[]).append(v)
    ...:     return acc
    ...:

In [17]: grouped_data = {k:accumulate(d) for k,d in data}

In [18]: grouped_data
Out[18]:
{'3': OrderedDict([('pos', ['28', '34']),
              ('idx2', ['3', '3']),
              ('val2', ['G', 'C']),
              ('val1', ['A', 'G']),
              ('idx1', ['4', '4'])]),
 '4': OrderedDict([('pos', ['41', '51']),
              ('idx2', ['4', '4']),
              ('val2', ['T', 'C']),
              ('val1', ['C', 'C']),
              ('idx1', ['4', '4'])]),
 '6': OrderedDict([('pos', ['11', '15', '23']),
              ('idx2', ['6', '6', '6']),
              ('val2', ['A', 'T', 'T']),
              ('val1', ['C', 'A', 'T']),
              ('idx1', ['4', '4', '4'])])}
注意,我使用了列表(和dict)理解。他们的工作相似。列表理解相当于:

data = []
for k, g in grouped:
    data.append((k, list(g))
为了更好的衡量,这里有一个相当于听写理解的例子,尽管我使用的是OrderedICT,因为在任何情况下,顺序似乎都很重要:

In [20]: grouped_data = collections.OrderedDict()

In [21]: for k, d in data:
    ...:     grouped_data[k] = accumulate(d)
    ...:

In [22]: grouped_data
Out[22]:
OrderedDict([('6',
              OrderedDict([('val2', ['A', 'T', 'T']),
                           ('val1', ['C', 'A', 'T']),
                           ('pos', ['11', '15', '23']),
                           ('idx2', ['6', '6', '6']),
                           ('idx1', ['4', '4', '4'])])),
             ('3',
              OrderedDict([('val2', ['G', 'C']),
                           ('val1', ['A', 'G']),
                           ('pos', ['28', '34']),
                           ('idx2', ['3', '3']),
                           ('idx1', ['4', '4'])])),
             ('4',
              OrderedDict([('val2', ['T', 'C']),
                           ('val1', ['C', 'C']),
                           ('pos', ['41', '51']),
                           ('idx2', ['4', '4']),
                           ('idx1', ['4', '4'])]))])
注意,我们可以一次完成所有操作,避免创建不必要的数据结构:

import itertools, io, csv, collections

data_stream = csv.DictReader(io.StringIO(raw_data), delimiter="\t")
grouped = itertools.groupby(data_stream, key=lambda x:x['idx2'])

def accumulate(data):
    acc = collections.OrderedDict()
    for d in data:
        for k,v in d.items():
            acc.setdefault(k,[]).append(v)
    return acc

grouped_data = collections.OrderedDict()
for k, g in grouped:
    grouped_data[k] = accumulate(g)
给定的

import io
import csv
import itertools as it
import collections as ct    

data="""pos\tidx1\tval1\tidx2\tval2
11\t4\tC\t6\tA
15\t4\tA\t6\tT
23\t4\tT\t6\tT
28\t4\tA\t3\tG
34\t4\tG\t3\tC
41\t4\tC\t4\tT
51\t4\tC\t4\tC"""
第一部分


如何将其转换为非iter类型的数据

代码

以下是如何保留迭代器中的数据-只需将其转换为列表:

>>> input_file = list(csv.DictReader(io.StringIO(data), delimiter = "\t"))
>>> input_file
[{'idx1': '4', 'idx2': '6', 'pos': '11', 'val1': 'C', 'val2': 'A'},
 {'idx1': '4', 'idx2': '6', 'pos': '15', 'val1': 'A', 'val2': 'T'},
 {'idx1': '4', 'idx2': '6', 'pos': '23', 'val1': 'T', 'val2': 'T'},
 {'idx1': '4', 'idx2': '3', 'pos': '28', 'val1': 'A', 'val2': 'G'},
 {'idx1': '4', 'idx2': '3', 'pos': '34', 'val1': 'G', 'val2': 'C'},
 {'idx1': '4', 'idx2': '4', 'pos': '41', 'val1': 'C', 'val2': 'T'},
 {'idx1': '4', 'idx2': '4', 'pos': '51', 'val1': 'C', 'val2': 'C'}]
或者使用列表:

>>> file_blocks = [(k, list(g)) for k, g in it.groupby(input_file, key=lambda x: x["idx2"])]
>>> file_blocks
[('6',
  [{'idx1': '4', 'idx2': '6', 'pos': '11', 'val1': 'C', 'val2': 'A'},
   {'idx1': '4', 'idx2': '6', 'pos': '15', 'val1': 'A', 'val2': 'T'},
   {'idx1': '4', 'idx2': '6', 'pos': '23', 'val1': 'T', 'val2': 'T'}]),
 ('3',
  [{'idx1': '4', 'idx2': '3', 'pos': '28', 'val1': 'A', 'val2': 'G'},
   {'idx1': '4', 'idx2': '3', 'pos': '34', 'val1': 'G', 'val2': 'C'}]),
 ('4',
  [{'idx1': '4', 'idx2': '4', 'pos': '41', 'val1': 'C', 'val2': 'T'},
   {'idx1': '4', 'idx2': '4', 'pos': '51', 'val1': 'C', 'val2': 'C'}])]
现在,您可以重用
输入文件
文件块
中的数据


第二部分

如何进一步处理此groupby对象以将值合并到同一组/块中具有公用键的列表中

类似于orderedDict,defaultDict,其中数据读取的顺序被保留

输出

[OrderedDict([('6',
               defaultdict(list,
                           {'idx1': ['4', '4', '4'],
                            'idx2': ['6', '6', '6'],
                            'pos': ['11', '15', '23'],
                            'val1': ['C', 'A', 'T'],
                            'val2': ['A', 'T', 'T']}))]),
 OrderedDict([('3',
               defaultdict(list,
                           {'idx1': ['4', '4'],
                            'idx2': ['3', '3'],
                            'pos': ['28', '34'],
                            'val1': ['A', 'G'],
                            'val2': ['G', 'C']}))]),
 OrderedDict([('4',
               defaultdict(list,
                           {'idx1': ['4', '4'],
                            'idx2': ['4', '4'],
                            'pos': ['41', '51'],
                            'val1': ['C', 'C'],
                            'val2': ['T', 'C']}))])]

itertools.groupby()
元素的顺序由
collections.orderedict()维护。文件各行之间的值顺序(请参见
输入文件
中的dicts)由
集合.defaultdict()对象中的列表保留。

“但是,由于输出已耗尽,我无法打印,请多次使用它来调试它。”。。。你有没有试着把它放进某个容器里,比如
列表
而不是打印?@sKwa:Oops!打字错误现在修复了。@juanpa.arrivillaga:我已经试过了。但是,我无法修复它。此外,任何下游分析都只是将其作为迭代器。有什么建议吗?你到底试过什么?看起来您似乎理解了如何通过迭代器对组进行迭代,所以,您不能用结果填充一个组吗?“如何将其转换为非iter类型的数据”强制转换为
list()
,以保留迭代器的内容。*吹毛求疵:这些不是生成器。我讨论了使用迭代器这个术语,但也许你是对的,你不相信我吗<代码>导入类型;打印(isinstance(输入文件,types.GeneratorType))
我不怀疑您。抢手货谢谢。我知道这很迂腐,但自从引入协同程序以来,生成器已经不仅仅是编写迭代器的便捷方式。谢谢@juanpa。我现在正试图在forloop中访问数据(分组的_数据)
对于x,y在分组数据中:print(x)
但是我得到了这个错误消息
对于x,y在分组数据中:ValueError:没有足够的值来解包(预期2,得到1)
@everestial007你问的是如何迭代字典(
有序dict
对象是
dict
对象)现在,从整个有序dict,我正在尝试访问嵌套的
OrderedDict
键:值
,以便进一步处理。@everestal007它们是字典。考虑<代码> GoePosiLoad数据[6′] [POS’< /代码>,但我不理解输出。代码>用于分组数据['6']['pos']:打印(k)
输出:1 2。我看不出输出的是什么。
def collate_data(data):
    """Yield an OrderedDict of merged dictionaries from `data`."""
    for idx, item in data:
        results = ct.OrderedDict()
        dd = ct.defaultdict(list)
        for dict_ in item:
            for k, v in dict_.items():
                dd[k].append(v)
        results[idx] = dd
        yield results
    

list(collate_data(file_blocks))
[OrderedDict([('6',
               defaultdict(list,
                           {'idx1': ['4', '4', '4'],
                            'idx2': ['6', '6', '6'],
                            'pos': ['11', '15', '23'],
                            'val1': ['C', 'A', 'T'],
                            'val2': ['A', 'T', 'T']}))]),
 OrderedDict([('3',
               defaultdict(list,
                           {'idx1': ['4', '4'],
                            'idx2': ['3', '3'],
                            'pos': ['28', '34'],
                            'val1': ['A', 'G'],
                            'val2': ['G', 'C']}))]),
 OrderedDict([('4',
               defaultdict(list,
                           {'idx1': ['4', '4'],
                            'idx2': ['4', '4'],
                            'pos': ['41', '51'],
                            'val1': ['C', 'C'],
                            'val2': ['T', 'C']}))])]