Я построил несколько больших фреймов данных, которые соответствуют контактам в сетевом графе. Формат этих DataFrames - строки, где значение индекса является уникальным идентификатором узла в графе, а столбец 1 является целым числом, которое соответствует «типу» узла (вы можете думать об этом как о цвете, например, все типа 1 красного цвета):
import pandas as pd
df = pd.read_csv(
"https://gist.githubusercontent.com/ethanagbaker/98062ebc83b3dd2018a1837d3e3b12df/raw/a59cb7645f6ca935e01a8dea04377da28847c365/testData.csv",
skiprows=1, header=None, index_col=0
)
Столбцы 3-24 - это идентификаторы узлов, которые совместно используют ребро с узлом, указанным индексом строки, где 0 указывает на отсутствие соседа. Таким образом, если столбцы 3 и 4 в строке 1 имеют ненулевые значения, узел 1 имеет преимущество перед указанными узлами. Столбцы 25-32 предназначены для указания количества соседних узлов каждого типа для узла, указанного индексом, и инициализируются как нули. Вот пример того, как эти данные выглядят: https://imgur.com/LtKRM38. Узел 1 относится к типу 6 с 6 соседями: 373, 389, 175, 99, 127 и 167.
У меня есть функциональный код, который перебирает строки, проверяет столбцы, которые определяют соседние узлы, затем ищет их тип в кадре данных и увеличивает столбец count. Это работает с желаемым эффектом, но медленно. Для ясности, счет для типа n
указан в столбцах n + 24
. Время выполнения составляет около 4 минут на кадре из 500 строк, но мне нужно увеличить его до ~ 50 000 000 строк. Я пытался изменить это, чтобы использовать .apply()
или векторизованный подход, но не совсем понимаю, как это сделать. Вот полностью функциональный итеративный подход:
def countNeighbors(contactMap):
for index, row in contactMap.iterrows():
for col in range(3,25):
cellID = row[col]
if cellID == 0:
break
else:
cellType = contactMap[1][cellID]
contactMap[24+cellType][index] += 1
return contactMap
#run the function
contactMapCounted = countNeighbors(contactMap)
contactMap
- матрица, описанная выше, и я экспортировал образец здесь . Обратите внимание, что индекс и заголовок включены и важны . Загрузка этого как панды DataFrame
должна позволить вам повторить это.
Полагаю, я просто долго смотрел на это, чтобы посмотреть, что здесь делать, но есть ли очевидный способ ускорить это?
Вероятно, уместное редактирование : После более глубокого тестирования кажется, что одна эта функция довольно быстрая, но я использую ее следующим образом, где я замечаю существенное замедление:
n_shuffles = 100
while s < n_shuffles:
#print(s)
contactMap_Shuffled = contactMap.sample(frac=1).reset_index(drop=True)
contactMap_Shuffled.index += 1
contactMap_Shuffled.loc[:,25:] = 0 #Reset the count cols
contactMap_Shuffled = countNeighbors(contactMap_Shuffled)
s += 1
Это сделано для того, чтобы рандомизировать индекс кадра, а затем пересчитать значения счетчика, как описано. Именно здесь я впервые заметил замедление и предположил, что проблема связана с countNeighbors()
, но, возможно, это что-то здесь ...