将交叉表转换为列而不在python中使用pandas

问题描述 投票:0回答:1

如何在不使用pandas的情况下将交互式数据从下面提到的输入文件转换为基于输入列表的列?

输入列表

[A,B,C]

输入数据文件

标签A,B,C仅用于表示,原始文件仅具有数值。我们可以根据输入列表的长度忽略colums XX和YY

  A B C XX YY
A 0 2 3 4  8
B 4 0 6 4  8
C 7 8 0 5  8

输出(输出需要有标签)

A A 0
A B 2
A C 3
B A 4
B B 0
B C 6
C A 7
C B 8
C C 0

标签需要出现在输出文件中,即使它出现在输入文件中,因此我在输出文件中提到了它的表示。

注意:实际上,标签是按照升序排序的城市名称,没有重复,而不是像A或B这样的单个字母。

不幸的是,如果我可以在服务器上安装pandas并使用unstack(),这会更容易,但是现在这个旧服务器上不允许安装。这是在python 3.5上

python csv crosstab
1个回答
1
投票

考虑到您标记了帖子csv,我假设实际输入数据是.csv文件,没有标题,如您所示。

所以示例数据看起来像:

0,2,3,4,8
4,0,6,4,8
7,8,0,5,8

如果标签是作为列表提供的,则匹配列和行的顺序(即['A', 'B', 'C'],这会将示例输出转换为:

'A','A',0
'A','B',2
'A','C',3
'B','A',4
etc.

请注意,这意味着文件中的行数和列数不能超过提供的标签数。

您指出标有“XX”和“YY”的列将被忽略,但您没有指出应该如何传达,但您确实提到输入的长度是确定它,所以我假设这意味着'列n后的所有内容都可以忽略'。

这是一个简单的实现:

from csv import reader


def unstack_csv(fn, columns, labels):
    with open(fn) as f:
        cr = reader(f)
        row = 0
        for line in cr:
            col = 0
            for x in line[:columns]:
                yield labels[row], labels[col], x
                col += 1
            row += 1


print(list(unstack_csv('unstack.csv', 3, ['A', 'B', 'C'])))

或者如果你喜欢简短而甜蜜的话:

from csv import reader

with open('unstack.csv') as f:
    content = reader(f)
    labels = ['A', 'B', 'C']
    print([(labels[row], labels[col], x)
           for row, data in enumerate(content)
           for col, x in enumerate(data) if col < 3])

(我也假设使用numpy已经出局,出于与熊猫相同的原因,但像csv那样的东西,因为它是标准库)

如果您不想明确提供标签,但只想生成它们,您可以执行以下操作:

def label(n):
    r = n // 26
    c = chr(65 + (n % 26))
    if r > 0:
        return label(r-1)+c
    else:
        return c

然后当然只是从示例中删除labels并替换为调用label(col)label(row)

© www.soinside.com 2019 - 2024. All rights reserved.