Создайте «матрицу корреляции» для двух списков, чтобы проверить, есть ли у значений что-то общее

#python #arrays #pandas #dataframe #nested

#питон #массивы #панды #фрейм данных #вложенный

Вопрос:

Не мог бы кто-нибудь, пожалуйста, помочь мне со следующим?

У меня есть один фрейм данных с двумя столбцами: продукты и интернет-магазины (n x 2) с n продуктами. Теперь я хотел бы получить двоичную матрицу (n x n) со всеми продуктами, перечисленными в качестве индексов, и всеми продуктами, перечисленными в качестве имен столбцов. Затем каждая ячейка должна содержать 1 или 0, обозначающие, был ли продукт в индексе и названии столбца из одного и того же интернет-магазина.

Следующий код возвращает то, чего я хотел бы достичь.

 dist = np.empty((len(df_title), len(df_title)), int)  for i in range(0,len(df_title)):  for j in range(0,len(df_title)):  boolean = df_title.values[i][1] == df_title.values[j][1]  dist[i][j] = boolean  df = pd.DataFrame(dist)  

Однако этот код занимает довольно значительное время уже для n = 1624. Поэтому мне было интересно, есть ли у кого-нибудь идея для более быстрого алгоритма.

Спасибо!

Ответ №1:

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

 lookup = df_title.values[:, 1]  

Кроме того, поскольку вы хотите интерпретировать полученную матрицу как bool -матрицу, вам, вероятно, следует указать dtype=bool (1 байт на поле) вместо dtype=int (8 байт на поле), что также сокращает потребление памяти на 8.

 dist = np.empty((len(df_title), len(df_title)), dtype=bool)  

Ваша матрица в любом случае будет симметричной по диагонали, поэтому вам нужно вычислить только «половину» матрицы, также если i == j мы знаем, что соответствующее поле в матрице должно быть True .

 lookup = df_title.values[:, 1] dist = np.empty((len(df_title), len(df_title)), dtype=bool)  for i in range(len(df_title)):  for j in range(len(df_title)):  if i == j:  # diagonal  dist[i, j] = True  else:  # symmetric along diagonal  dist[i, j] = dist[j, i] = lookup[i] == lookup[j]  

Кроме того, используя numpy-широковещание, вы могли бы фактически преобразовать все это в одну строку кода, что на порядки быстрее, чем for решение с двойным циклом:

 lookup = df_title.values[:, 1] dist = lookup[None, :] == lookup[:, None]  

Комментарии:

1. Большое спасибо! Это было именно то, что я искал, и очень информативно.