Python 将巨大的三列表转换为表的脚本

Python 将巨大的三列表转换为表的脚本,python,r,algorithm,scripting,import-from-csv,Python,R,Algorithm,Scripting,Import From Csv,我有一组以下3列格式的数据(CSV文件): A, B, C 3277,4733,54.1 3278,4741,51.0 3278,4750,28.4 3278,4768,36.0 3278,4776,50.1 3278,4784,51.4 3279,4792,82.6 3279,4806,78.2 3279,4814,36.4 我需要一个三向列联表,比如:(对不起,这看起来不太好) 类似于excel“透视表”、OpenOffice数据试点或R“表(x、y、z)” 问题是我的数

我有一组以下3列格式的数据(CSV文件):

A, B, C
3277,4733,54.1 
3278,4741,51.0 
3278,4750,28.4 
3278,4768,36.0 
3278,4776,50.1 
3278,4784,51.4 
3279,4792,82.6 
3279,4806,78.2 
3279,4814,36.4 
我需要一个三向列联表,比如:(对不起,这看起来不太好)

类似于excel“透视表”、OpenOffice数据试点或R“表(x、y、z)”

问题是我的数据集非常庞大(总共超过500000行,在A和B中有大约400个不同的因子。(OOo、MSO和R限制阻止了实现这一点)

我相信Python脚本可以用来创建这样一个表。a和B都是数字(但可以被视为字符串)

有人处理过这个问题吗? (伪代码或C或Java代码也受欢迎……但我更喜欢python,因为它实现起来更快:)

编辑: 下面的Python脚本几乎提供了我想要的内容,但是,在编写输出文件时,我可以看到我正在编写的“头”中的值(取自第一行)与其他行不对应

from collections import defaultdict as dd
d = dd(lambda: dd(float))

input =  open("input.txt")
output = open("output.txt","w")
while 1:
    line = input.readline()
    if not line:
        break
    line = line.strip('\n').strip('\r')
    splitLine = line.split(',')
    if (len(splitLine) <3):
        break
    d[splitLine[0]][splitLine[1]] = splitLine[2]

output.write("\t")
for k,v in d.items()[0][1].items():
    output.write(str(k)+"\t")
output.write("\n")
for k,v in d.items():
    output.write(k+"\t")
    for k2,v2 in v.items():
        output.write(str(v2)+"\t")
    output.write("\n")
从集合导入defaultdict作为dd
d=dd(λ:dd(浮动))
输入=打开(“input.txt”)
输出=打开(“output.txt”、“w”)
而1:
line=input.readline()
如果不是直线:
打破
line=line.strip('\n').strip('\r'))
splitLine=line.split(',')

如果(len(splitLine)当你只有一把锤子时

从概念上讲,您试图做的很简单,但由于数据的大小,计算起来很困难。我倾向于使用R,因为它具有分析和图形能力,而不是数据争用技能。当我需要移动一堆数据时,我通常只将所有内容都粘贴到数据库中

最近,我在SQLite和R方面取得了相当大的成功。最好的部分是您可以实际使用R读取数据,这使得导入大型SPSS文件或SQLite无法真正处理但R可以处理的其他数据源变得非常容易

下面是我推荐的工作流程

  • 将数据导入R(完成)
  • 图书馆(RSQLite)
  • 将数据帧移动到SQLite
  • 在A列和B列上创建索引
  • 创建用于生成表的视图
  • 从R查询视图,并将返回强制到表中

  • 当你只有一把锤子

    从概念上讲,您试图做的很简单,但由于数据的大小,计算起来很困难。我倾向于使用R,因为它具有分析和图形能力,而不是数据争用技能。当我需要移动一堆数据时,我通常只将所有内容都粘贴到数据库中

    最近,我在SQLite和R方面取得了相当大的成功。最好的部分是您可以实际使用R读取数据,这使得导入大型SPSS文件或SQLite无法真正处理但R可以处理的其他数据源变得非常容易

    下面是我推荐的工作流程

  • 将数据导入R(完成)
  • 图书馆(RSQLite)
  • 将数据帧移动到SQLite
  • 在A列和B列上创建索引
  • 创建用于生成表的视图
  • 从R查询视图,并将返回强制到表中

  • 如果您可以在R中使用
    table(x,y,z)
    ,那么如何试用处理如此庞大数据集的内存外R包?使用包中的
    read.big.matrix
    函数读取数据集,使用包中的
    bigtable
    函数创建表


    请参阅。

    如果您可以在R中使用
    表(x,y,z)
    ,那么如何试用处理如此巨大数据集的内存不足的R包?使用包中的
    read.big.matrix
    函数读取数据集,并使用包中的
    bigtable
    函数创建表

    请参见。

    在R中,我可以这样做:

    N <- 1000000
    x <- sample(1:400,N,TRUE)
    y <- sample(1:400,N,TRUE)
    z <- sample(1:400,N,TRUE)
    
    w <- table(x,y,z)
    
    N在R中,我可以这样做:

    N <- 1000000
    x <- sample(1:400,N,TRUE)
    y <- sample(1:400,N,TRUE)
    z <- sample(1:400,N,TRUE)
    
    w <- table(x,y,z)
    

    N在我看来,您所需输出的示例不像是一个三向列联表。这将是从(键1、键2、键3)到发生次数计数的映射。您的示例看起来像是从(键1、键2)到某个数字的映射。您没有说当(键1、键2)重复时要做什么:平均值、总计值、其他值

    假设您想要一个总数,下面是Python中的一种节省内存的方法,使用嵌套的
    defaultdict
    s:

    >>> from collections import defaultdict as dd
    >>> d = dd(lambda: dd(float))
    >>> d[3277][4733] += 54.1
    >>> d
    defaultdict(<function <lambda> at 0x00D61DF0>, {3277: defaultdict(<type 'float'>, {4733: 54.1})})
    >>> d[3278][4741] += 51.0
    >>> d
    defaultdict(<function <lambda> at 0x00D61DF0>, {3277: defaultdict(<type 'float'>, {4733: 54.1}), 3278: defaultdict(<type 'float'>, {4741: 51.0})})
    >>>
    
    如果您在将这些数据分组后说出您想要对其执行的操作,可能会有所帮助


    如果您想要(例如)一个平均值,您有两个选项:(1)两个数据结构,一个用于合计,一个用于计数,然后执行“average=total-count”(2)对前两列的数据进行排序,使用itertools.groupby将重复数据收集在一起,进行计算,并将结果添加到“average”中数据结构。很难说哪种方法会占用更少的内存;Python是Python,您可以很快尝试这两种方法。

    您所需输出的示例在我看来不像是一个三向列联表。这将是从(key1,key2,key3)到发生次数的映射。您的示例看起来像是从(key1,key2)的映射当(键1,键2)被复制时,你不说该做什么:平均值,总数,其他什么

    假设您想要一个总数,下面是Python中的一种节省内存的方法,使用嵌套的
    defaultdict
    s:

    >>> from collections import defaultdict as dd
    >>> d = dd(lambda: dd(float))
    >>> d[3277][4733] += 54.1
    >>> d
    defaultdict(<function <lambda> at 0x00D61DF0>, {3277: defaultdict(<type 'float'>, {4733: 54.1})})
    >>> d[3278][4741] += 51.0
    >>> d
    defaultdict(<function <lambda> at 0x00D61DF0>, {3277: defaultdict(<type 'float'>, {4733: 54.1}), 3278: defaultdict(<type 'float'>, {4741: 51.0})})
    >>>
    
    如果您在将这些数据分组后说出您想要对其执行的操作,可能会有所帮助


    如果您想要(例如)一个平均值,您有两个选项:(1)两个数据结构,一个用于合计,一个用于计数,然后执行“average=total-count”(2)对前两列的数据进行排序,使用itertools.groupby将重复数据收集在一起,进行计算,并将结果添加到“average”中数据结构。很难说哪种方法会占用更少的内存;Python是Python,您可以很快地尝试这两种方法。

    dict的一个小的子类可以为您提供一个方便的ob
    >>> d2 = dd(float)
    >>> d2[3277,4733] += 54.1
    >>> d2
    defaultdict(<type 'float'>, {(3277, 4733): 54.1})
    >>> d2[3278,4741] += 51.0
    >>> d2
    defaultdict(<type 'float'>, {(3277, 4733): 54.1, (3278, 4741): 51.0})
    >>>
    
    import csv
    class ContingencyTable(dict):
        def __init__(self):
            self.a_keys=set()
            self.b_keys=set()
            dict.__init__(self)
        def __setitem__(self, key,value):
            self.a_keys.add(key[0])
            self.b_keys.add(key[1])
            dict.__setitem__(self, key, value)
        def feed(self, file):
            reader = csv.reader(file)
            reader.next()
            for a, b, c in reader:
                self[int(a),int(b)] = float(c)
    
    table = ContingencyTable()
    table.feed(open("yourfile.csv"))
    
    d = {}
    col_label_set = set()
    row_label_set = set()
    input =  open("input.txt")
    output = open("output.txt","w")
    for line in input:
        line = line.strip()
        splat = line.split(',')
        if len(splat) != 3:
            break # error message???
        k1, k2, v = splat
        try:
            subdict = d[k1]
        except KeyError:
            subdict = {}
            d[k1] = subdict
        subdict[k2] = v
        row_label_set.add(k1)
        col_label_set.add(k2)
    col_labels = sorted(col_label_set)
    row_labels = sorted(row_label_set
    output.write("\t")
    for v in col_labels::
        output.write(v + "\t")
    output.write("\n")
    for r in row_labels:
        output.write(r + "\t")
        for c in col_labels:
            output.write(d[r].get(c, "") + "\t")
        output.write("\n")
    
    class SparseTable(object):
    
        def __init__(self, iterable):
            d = {}
            col_label_set = set()
            for row_label, col_label, value in iterable:
                try:
                    subdict = d[row_label]
                except KeyError:
                    subdict = {}
                    d[row_label] = subdict
                subdict[col_label] = value
                col_label_set.add(col_label)
            self.d = d
            self.col_label_set = col_label_set
    
        def tabulate(self, row_writer, corner_label=u"", missing=u""):
            d = self.d
            col_labels = sorted(self.col_label_set)
            row_labels = sorted(d.iterkeys())
            orow = [corner_label] + col_labels
            row_writer(orow)
            for row_label in row_labels:
                orow = [row_label]
                subdict = d[row_label]
                for col_label in col_labels:
                    orow.append(subdict.get(col_label, missing))
                row_writer(orow)
    
    if __name__ == "__main__":
    
        import sys
    
        test_data = u"""
        3277,4733,54.1
        3278,4741,51.0
        3278,4750,28.4
        3278,4768,36.0
        3278,4776,50.1
        3278,4784,51.4
        3279,4792,82.6
        3279,4806,78.2
        3279,4814,36.4
        """.splitlines(True)
    
        def my_writer(row):
            sys.stdout.write(u"\t".join(row))
            sys.stdout.write(u"\n")
    
        def my_reader(iterable):
            for line in iterable:
                line = line.strip()
                if not line: continue
                splat = line.split(u",")
                if len(splat) != 3:
                    raise ValueError(u"expected 3 fields, found %d" % len(splat))
                yield splat
    
        table = SparseTable(my_reader(test_data))
        table.tabulate(my_writer, u"A/B", u"....")
    
    A/B     4733    4741    4750    4768    4776    4784    4792    4806    4814
    3277    54.1    ....    ....    ....    ....    ....    ....    ....    ....
    3278    ....    51.0    28.4    36.0    50.1    51.4    ....    ....    ....
    3279    ....    ....    ....    ....    ....    ....    82.6    78.2    36.4