Реструктуризация массива numpy на основе списка столбцов и строк (например, сводной таблицы в массиве numpy)

#python #numpy #numpy-ndarray

#питон #тупица #numpy-ndarray

Вопрос:

Вот пример источника данных numpy

 col row1 row2 row3 row4 columns [[( 11.2, '689', '197', 'value_2', 0, 1)]  [( 56.4, '689', '197', 'value_3', 0, 1)]  [( 195.7, '689', '197', 'value_2', 0, 2)]  [( 565.2, '689', '197', 'value_3', 0, 2)]  [( 227.6, '689', '197', 'value_2', 0, 3)]  [( 1347.6, '689', '197', 'value_2', 0, 3)]  [( 613.5, '689', '196', 'value_2', 0, 1)]  [(139. , '689', '196', 'value_3', 0, 1)]  [( 6011. , '689', '196', 'value_2', 0, 2)]  [(103. , '689', '196', 'value_3', 0, 2)]  [( 6860. , '689', '196', 'value_2', 0, 3)]  [(1302. , '689', '196', 'value_3', 0, 3)]  [( 1787.9, '622', '197', 'value_2', 0, 1)]  [( 632.5, '622', '197', 'value_3', 0, 1)]  [( 178.8, '622', '197', 'value_2', 0, 2)]  [( 6360.5, '622', '197', 'value_3', 0, 2)]  [( 228. , '622', '196', 'value_2', 0, 1)]  [(672. , '622', '196', 'value_3', 0, 2)]  ]  

Таким образом, из этого ожидаемый результат должен быть

 1 2 3  row1 row2 row3 row4 689 197 value_2 0 11.2 195.7 227.6 689 197 value_3 0 56.4 565 1347 689 196 value_2 0 613.5 6011 6860 689 196 value_3 0 139 103 1302 622 197 value_2 0 1787 178  622 197 value_3 0 632 6360  

Выше 1 2 3 столбцов получают из одного столбца в массиве numpy, то есть ранг

Исходя из приведенных данных, строка 1 всегда будет 1, но она имеет несколько строк 2, 3 и 4. Для каждых данных в строке 1 следует найти эквивалентные строки и заполнить их, как указано в выходных данных.

Я попробовал приведенный ниже код, но не смог правильно получить значения столбцов (1, 2, 3), так как он находится в другом месте, которое я не мог взять и записать в массив numpy.

 new_temp_arr = 'actual_data_given' m = 1 row_list = ['row1', 'row2', 'row3', 'row4'] # Column list taken from the array based on rank column column_list = [1, 2, 3] sample_list = []  for value in new_temp_arr:  for new_value in new_temp_arr:  if m gt;= len(new_temp_arr):  break  new_value = new_temp_arr[m]  # Checking all the values for the rows matches with one another  condition = [value[row] == new_value[row] for row in row_list]  if all(condition):  # Looping through all the column list and getting the float value  # I'm stuck here, how to store the values with properly matched data  for per in column_list:  if new_value['rank'] == [per]:  float_value = new_value['float_value']  sample_list.append(new_value)  m  = 1  

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

1. Природа «образца источника данных numpy» неясна. Заголовки столбцов не являются частью массива. Вложенность [] и () предполагают, что это структурированный массив, но вы не указали ни форму, ни тип dtype. Но это может быть тип объекта dtype или просто списки кортежей. Я не думаю numpy , что это поможет здесь. Для операций группировки , которые я люблю использовать dict , или даже collections.defaultdict .

2. Да, это структурированные массивы, dtype, который я упомянул как строки col и т. Д.. Спасибо за вклад, который я пытаюсь внести с помощью defaultdict

3. Знаете ли вы полный набор уникальных row# значений заранее?

4. Уникальная строка, означает, о чем именно вы спрашиваете?

Ответ №1:

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

Кроме того, похоже, что ваш вывод представляет собой фрейм данных, так почему бы не использовать pandas его непосредственно с pivot_table и aggfunc='first' ?:

 a = np.array([[( 11.2, '689', '197', 'value_2', 0, 1)],  [( 56.4, '689', '197', 'value_3', 0, 1)],  [( 195.7, '689', '197', 'value_2', 0, 2)],  [( 565.2, '689', '197', 'value_3', 0, 2)],  [( 227.6, '689', '197', 'value_2', 0, 3)],  [( 1347.6, '689', '197', 'value_2', 0, 3)],  [( 613.5, '689', '196', 'value_2', 0, 1)],  [(139. , '689', '196', 'value_3', 0, 1)],  [( 6011. , '689', '196', 'value_2', 0, 2)],  [(103. , '689', '196', 'value_3', 0, 2)],  [( 6860. , '689', '196', 'value_2', 0, 3)],  [(1302. , '689', '196', 'value_3', 0, 3)],  [( 1787.9, '622', '197', 'value_2', 0, 1)],  [( 632.5, '622', '197', 'value_3', 0, 1)],  [( 178.8, '622', '197', 'value_2', 0, 2)],  [( 6360.5, '622', '197', 'value_3', 0, 2)],  [( 228. , '622', '196', 'value_2', 0, 1)],  [(672. , '622', '196', 'value_3', 0, 2)],  ]) cols = ['col', 'row1', 'row2', 'row3', 'row4', 'columns'] (pd.DataFrame(a[:,0,:], columns=cols)  .pivot_table(index=['row1', 'row2', 'row3', 'row4'], columns='columns', values='col', aggfunc='first') )  

выход:

 columns 1 2 3 row1 row2 row3 row4  622 196 value_2 0 228.0 NaN NaN  value_3 0 NaN 672.0 NaN  197 value_2 0 1787.9 178.8 NaN  value_3 0 632.5 6360.5 NaN 689 196 value_2 0 613.5 6011.0 6860.0  value_3 0 139.0 103.0 1302.0  197 value_2 0 11.2 195.7 227.6  value_3 0 56.4 565.2 NaN  

Если заказ важен, вы можете reindex вернуться к первоначальному заказу:

 cols = ['col', 'row1', 'row2', 'row3', 'row4', 'columns'] df = pd.DataFrame(a[:,0,:], columns=cols)  idx = df.set_index(['row1', 'row2', 'row3', 'row4']).index idx = idx[~idx.duplicated(keep='first')]  (df.pivot_table(index=['row1', 'row2', 'row3', 'row4'], columns='columns', values='col', aggfunc='first')  .reindex(idx) )  

выход:

 columns 1 2 3 row1 row2 row3 row4  689 197 value_2 0 11.2 195.7 227.6  value_3 0 56.4 565.2 NaN  196 value_2 0 613.5 6011.0 6860.0  value_3 0 139.0 103.0 1302.0 622 197 value_2 0 1787.9 178.8 NaN  value_3 0 632.5 6360.5 NaN  196 value_2 0 228.0 NaN NaN  value_3 0 NaN 672.0 NaN  

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

1. Я должен использовать только numpy, это требование. Порядок — это не проблема. Любое значение может быть первым и последним, что не будет проблемой. Мне просто нужно извлечь эту структуру с помощью numpy.

Ответ №2:

 def get_list(arr, row1, row_column_values, row_list, column_list, index):  dict_keys = {i: [] for i in column_list}  dic = {row1: dict_keys}  for value in arr:  if index == len(arr):  index = 0  value = arr[index]  condition = [value[row][0] == row_column_values[row] for row in row_list]  if all(condition):  dic[row1][int(value['rank'][0])] = value['float_value'][0]  if index == 0:  break  index  = 1     new_temp_arr = 'actual_data_given' m = 1 row_list = ['row1', 'row2', 'row3', 'row4'] # Column list taken from the array based on rank column column_list = [1, 2, 3] out_array = np.zeros() #Numpy array with type dic = {}   for value in new_temp_arr:  row_values = {row: value[row][0] for row in row_list}  dic = get_list(new_temp_arr, value['row1'][0], row_values, row_list, column_list, m)  float_value = list(dic[value['row1'][0]].values())  out_array[out_index] = tuple(list(value[row_list][0])   float_value)  return out_array    

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