Использование Groupby для группировки столбцов в таблице доступа в Python - PullRequest
2 голосов
/ 12 октября 2011

Я какое-то время играл с функцией groupby из модуля itertools (например, дни)

for k, g in groupby(data, keyfunc):

У меня действительно проблемы с пониманием синтаксиса. Я пробовал множество разных вещей, но я действительно не знаю, что вставить для «data» и «keyfunc» и заставить его возвращать группы данных, которые я хочу в выражении print.

Что я делаю, так это циклически перебираю строки в таблице доступа.

Я установил переменную для поиска курсора (который отсортирован) в таблице доступа и вытащил нужный мне столбец.

for row in cursor:
    print row.ROAD_TYPE

Возвращает:

TRUNK ROAD
TRUNK ROAD
TRUNK ROAD
TRUNK ROAD
COLLECTOR HIGHWAY
COLLECTOR HIGHWAY
ACCESS ROAD
ACCESS ROAD
ACCESS ROAD
ACCESS ROAD
ACCESS ROAD
ACCESS ROAD
ACCESS ROAD
MAJOR ROAD
MAJOR HIGHWAY

Я хочу сгруппировать эти значения вместе, и он вернет мне строковое значение, поэтому будет напечатано что-то вроде этого:

TRUNK ROAD
TRUNK ROAD
TRUNK ROAD
TRUNK ROAD

COLLECTOR HIGHWAY
COLLECTOR HIGHWAY

ACCESS ROAD
ACCESS ROAD
ACCESS ROAD
ACCESS ROAD
ACCESS ROAD
ACCESS ROAD
ACCESS ROAD

MAJOR ROAD

MAJOR HIGHWAY

Наконец, я хочу сгруппировать второй столбец на основе этих новых групп, чтобы получить что-то вроде этого:

TRUNK ROAD  M1
TRUNK ROAD  M1

TRUNK ROAD  M2

TRUNK ROAD  M3


COLLECTOR HIGHWAY  M1

COLLECTOR HIGHWAY  M2


ACCESS ROAD  M1
ACCESS ROAD  M1

ACCESS ROAD  M3
ACCESS ROAD  M3

ACCESS ROAD  M7
ACCESS ROAD  M7

ACCESS ROAD  M8


MAJOR ROAD  M8


MAJOR HIGHWAY  M8

Я знаю, что это, вероятно, намного сложнее, чем я сам себе представлял, я чувствую, что есть простой ответ, но я совершенно ошарашен и не могу найти в Интернете пример, который объясняет групповой синтаксис таким образом, что я понимаю. Пожалуйста, почувствуй е

Ответы [ 3 ]

1 голос
/ 12 октября 2011

Идея itertools.groupby состоит в том, чтобы решить основную проблему: «Я хочу пройтись по последовательности, проанализировать каждую вещь в ней и, в зависимости от процесса анализа, каждую вещь по-своему».groupby разделяет последовательность на группы, но сохраняет порядок исходной последовательности .

from itertools import groupby
i = groupby(xrange(12), lambda v: v / 3)
results = [(x[0], list(x[1])) for x in i]
print str(results)

Вышеуказанные отпечатки: [(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9, 10, 11])]

Вы заметите, чточтобы получить список results, мне пришлось провести дополнительную обработку.То, что на самом деле дает groupby, предназначено для итерации:

i = groupby(xrange(12), lambda v: v / 3)
print str(i.next())

Вышеприведенные отпечатки: (0, <itertools._grouper object at 0x020BF3D0>)

Таким образом, идея заключается в том, что в вашей программе вы скажете key, valueiter = i.next(), testkey, а затем передайте valueiter правильной функции / методу обработки.

Так какое здесь значение?Что ж, вам не нужно продолжать тестировать ключ в ваших функциях обработки, чтобы сказать, когда остановиться.groupby автоматически остановит для вас каждый «итератор».

То, что groupby делает , а не , в отличие от предложения GROUP BY в SQL, гарантирует, что все сто же значение ключа из исходного итерируемого обрабатывается сразу.Значения ключа могут повторяться из groupby.Это оправдано, поскольку цель состоит в том, чтобы сохранить порядок исходной последовательности, а , а не , чтобы накапливать все в памяти.Например:

i = groupby(xrange(6), lambda v: v % 3)  # note: modulo division
results = [(x[0], list(x[1])) for x in i]
print str(results)

Приведенные выше отпечатки: [(0, [0]), (1, [1]), (2, [2]), (0, [3]), (1, [4]), (2, [5])].Значения ключа повторяются, и каждый подитератор создает только один элемент данных.Это наихудший сценарий с точки зрения производительности для groupby, и это означает, что вы должны следовать определенной модели при работе с этим инструментом.

Так что-то вроде этого:

i = groupby(xrange(12), lambda v: v / 3)
results = dict([(x[0], list(x[1])) for x in i])  # beware of dict() here!
print str(results)

правильно только в том случае, если вы знаете априори , что ваши значения ключа будут никогда повторяться.

1 голос
/ 13 октября 2011

Ваши два groupby примера сделаны точно так же, за исключением вашего выбора key

from itertools import groupby
from operator import attrgetter

for key, rows in groupby(cursor, key=attrgetter('ROAD_TYPE')):
    for row in rows:
        print row.ROAD_TYPE
    print

for key, rows in groupby(cursor, key=attrgetter('ROAD_TYPE', 'OTHER_COLUMN')):
    for row in rows:
        print row.ROAD_TYPE, row.OTHER_COLUMN
    print

В обоих случаях key будет результатом attrgetter (), но вам это на самом деле не понадобится, поскольку вы будете перебирать строки, сгруппированные по этому ключу. Конечно, все это работает правильно, если cursor отсортировано по тому же ключу, по которому вы группируете.

1 голос
/ 12 октября 2011
import itertools as it
for key, group in it.groupby(cursor, lambda row: row.ROAD_TYPE):
    for sec_col,pairs in it.groupby(group, lambda row: row.SECOND_COLUMN):
        for row in pairs:
            print('{t}  {s}'.format(t=row.ROAD_TYPE,s=row.SECOND_COLUMN))
        print
    print

Вот два примера, которые помогут grok groupby :

[list(g) for k, g in it.groupby('AAAABBBCCD')]
# [['A', 'A', 'A', 'A'], ['B', 'B', 'B'], ['C', 'C'], ['D']]

Выше все одинаковые элементы сгруппированы.

Теперь мы добавим ключевую функцию, keyfunc:

keyfunc=lambda x: x//3
data=range(13)
[list(g) for k,g in it.groupby(data,keyfunc)]
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12]]
[k for k,g in it.groupby(data,keyfunc)]
# [0, 1, 2, 3, 4]

Теперь вместо группировки по элементам данных мы группируем по keyfunc(x) для каждого x в data.

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