Создание и обход дерева, объединяющего уникальные значения из фрейма данных - PullRequest
0 голосов
/ 17 мая 2019

У меня есть небольшой фрейм данных (15 строк), и мне нужно сгенерировать случайную последовательность уникальных значений в этих столбцах.Эти значения взаимосвязаны.

Это пример таблицы:

enter image description here Пример: принимая каждое уникальное значение из канала, я должен иметь возможность сделатьпоследовательность движется вправо.До сих пор я жестко запрограммировал словарь и имел древовидную структуру, и использовал random.choice (), чтобы выбрать случайный ключ и продвинуться глубже в dict.

Но у меня есть больше таких таблиц, и было бы здоровоиметь древовидную структуру, а затем выбрать случайный путь от корня до листа.Это может быть несколько деревьев, начинающихся с каждого значения столбца Канала.

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

Пример: для отображения есть подканалы Instagram, GDisplay и google UAC, затем у каждого из подканалов есть субпартнер и, наконец, идентификатор кампании.Один из возможных случайных путей может быть следующим:

Отображение -> Instagram -> Instagram -> NA

Но это не может быть Поиск -> Instagram -> обычный ->.

Ответы [ 2 ]

0 голосов
/ 17 мая 2019

Признаюсь, я не совсем уверен, что вы имеете в виду в вопросе, но позвольте мне предложить следующее решение.

Если я правильно понимаю одну вещь, ваша конечная цель - каким-то образом преобразовать вашу собственную древовидную структуру, котораяиспользует dict в качестве хеш-таблицы для листьев каждого узла и может генерировать случайные пути этого дерева из него, равномерно распределенного.

Так что я думаю, ваш код должен был выглядеть примерно так:

import random

tree_node1 = {'value':1,'childs':[]}
tree_node2 = {'value':2,'childs':[]}
tree_node3 = {'value':3,'childs':[tree_node1]}
tree_node4 = {'value':4,'childs':[tree_node1, tree_node2]}
tree_node = {'value': 5, 'childs': [tree_node3,tree_node4]}


def random_path_recursive(node, trace = None):
    if trace is None:
        trace = []
    trace.append(node['value'])
    num_childs = len(node['childs'])
    if num_childs == 0:
        return trace
    else:
        node = node['childs'][random.randint(0,num_childs-1)]
        return random_path_recursive(node,trace)


print(random_path_recursive(tree_node))

Я не использовал какие-либо существенные структуры для простоты.

Во-первых, кроме рекурсивной функции, в этом подходе нет ничего плохого.Это поможет вам сохранить древовидную структуру и получить желаемый результат.Тем не менее, если вам потребуется много времени, это не будет очень быстрым без каких-либо потоков и параллелизма.

Вы также можете преобразовать рекурсивную функцию в нерекурсивную:

def random_path_nonrecursive(node):
    trace = []
    while True:
        trace.append(node['value'])
        num_childs = len(node['childs'])

        if num_childs == 0:
            return trace

        node = node['childs'][random.randint(0, num_childs - 1)]

print(random_path_nonrecursive(tree_node))

Наконец, если вы преобразуете его в файл данных Pandas, будет еще проще выбрать случайную строку.

Вы можете сделать это как

def make_rows(node, rows=None, trace=None):
    rows = [] if rows is None else rows
    trace = [] if trace is None else trace

    trace.append(node['value'])
    num_childs = len(node['childs'])
    if num_childs == 0:
        rows.append(trace)
        return rows
    else:
        for subnode in node['childs']:
            make_rows(subnode,rows, list(trace))
    return rows

import pandas as pd

def convert_to_df(node, headers=None):
    return pd.DataFrame(make_rows(node), columns=headers)

df = convert_to_df(tree_node, ['level_1','level_2','level_3'])
print(df.iloc[random.randint(0, df.shape[0])])

Хорошоудачи!

0 голосов
/ 17 мая 2019

Если у вас небольшой фрейм данных, вы можете использовать pandas для выполнения этой работы - чтобы найти все возможные пути, которые вы ищете:

import pandas as pd

df = pd.DataFrame({
    'Channel': list('abaabbcccaab'),
    'Partner': [1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 2, 3],
    'SubPartner': [10, 20, 10, 20, 10, 20, 30, 30, 30, 10, 10, 10],
    'CampaignId': [100, 100, 100, 100, 200, 200, 300, 300, 400, 0, 0, 0]})

# groupby - get all unique combinations
# size - simple way to count number of every combination
# reset_index - multindex to columns
df = df.groupby(df.columns.tolist()).size().reset_index()

print(df)

Выход:

  Channel  Partner  SubPartner  CampaignId  0
0       a        1          10           0  1
1       a        1          10         100  2
2       a        2          10           0  1
3       a        2          20         100  1
4       b        1          20         100  1
5       b        2          10         200  1
6       b        2          20         200  1
7       b        3          10           0  1
8       c        3          30         300  2
9       c        3          30         400  1

Каждая строка - это путь. В последнем столбце указано количество вхождений пути, таких как count (*) в sql.

...