конвертировать кросс-таблицу в столбцы без использования панд в Python - PullRequest
0 голосов
/ 04 апреля 2019

Как преобразовать данные кросс-таблицы из указанного ниже файла ввода в столбцы на основе списка ввода без использования панд?

Список ввода

[A,B,C]

Входной файл данных

Метки A, B, C предназначены только для представления, исходный файл имеет только числовые значения. Мы можем игнорировать столбцы 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 (), но на этом старом сервере установки сейчас запрещены. Это на питоне 3.5

1 Ответ

1 голос
/ 04 апреля 2019

Учитывая, что вы пометили сообщение 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).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...