Быстрый способ пересечения списка, сгенерированного с помощью цикла for, из кадра данных со значениями словаря с использованием алгоритма Single Pass

Классы являются ссылочными типами, поэтому, как вы заметили, все элементы массива в

var users = [User](count: howManyUsers, repeatedValue:User(thinkTime: 10.0))

ссылаются на один и тот же экземпляр объекта (который создается первым, а затем передается как аргумент инициализатору массива).

Для типа struct вы получите другой результат.

Возможное решение:

var users = (0 ..< howManyUsers).map { _ in User(thinkTime: 10.0) }

Здесь создается экземпляр User для каждого из индексов массива.

Если вам это нужно часто, вы можете определить метод инициализации массива, который принимает параметр «автозакрытия»:

extension Array {
    public init(count: Int, @autoclosure elementCreator: () -> Element) {
        self = (0 ..< count).map { _ in elementCreator() }
    }
}

var users = Array(count: howManyUsers, elementCreator: User(thinkTime: 10.0) )

Теперь второй аргумент User(thinkTime: 10.0) завершается компилятором в закрытие, а закрытие выполняется для каждого индекса массива.


Обновление для Swift 3:

extension Array {
    public init(count: Int, elementCreator: @autoclosure () -> Element) {
        self = (0 ..< count).map { _ in elementCreator() }
    }
}
2
задан thecruisy 16 January 2019 в 01:36
поделиться

1 ответ

Сила numpy / scipy / pandas заключается в использовании кода C для выполнения большей части работы за вас. Учитывая, что, по вашим словам, есть 300 тыс. Строк и 80 столбцов, я предлагаю вам сначала приложить все усилия, чтобы убедиться, что вы обрабатываете строки в C, а не в python. Таким образом, ваш первый цикл должен быть исключен: не обрабатывайте 300k элементов, используя python.

Как я читаю ваши требования, у вас есть индекс (метки строк), в котором есть значения какого-то типа, которые могут отображаться в отдельных ячейках в других ваших столбцах. Примерно так:

Index   A  B  C  D
  1     0  0  3  0
  2     2  0  1  -1
  3     0  0  0  0
  192   0  0  1  -1

Вы хотите знать, для каждого индекса, есть ли это значение в каком-либо из столбца A, столбца B, столбца C и т. Д. Если любое значение индекса появляется в столбце, этот столбец "ALIVE".

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

В моем примере выше столбец A считается живым из-за {2}, а столбец C считается живым из-за {3, 1}, но столбцы B и D не являются живыми, потому что они не содержат никаких значений, которые присутствуют в указателе. Это правильно?

Попробуйте использовать isin, чтобы определить, присутствуют ли значения в столбцах в индексе. Затем используйте any, чтобы свести логические результаты к одному логическому значению, которое определяет, является ли столбец живым:

row_labels = df.index
col_is_alive = df.isin(row_labels).any()  # NB: any(index=0) is default

(ПРИМЕЧАНИЕ: я не в том месте, где я могу запустить этот код. Это может содержат синтаксис или другие ошибки.)

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

alive_col_names = { name for name in df.columns if col_is_alive[name] }  # Set comprehension

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

col_dict = { key:alive_col_names - {key} for key in alive_col_names}

С другой стороны, если вы каким-то образом итеративно обновляете эти значения, я бы посоветовал вам сделать вашу вторую структуру данных словарём строки -> set вместо string -> list, так как это даст вам доступ стандартным операциям над множеством и поведению.

new_col_dict = {}

for key, other_cols in col_dict.items():
    if key not in alive_col_names:
        continue

    new_col_dict[key] = other_cols.interset(alive_col_names)

col_dict = new_col_dict

(Которые могут быть свернуты с использованием разборчивого понимания, но, возможно, не в интересах читабельности.)

0
ответ дан aghast 16 January 2019 в 01:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: