Сопоставление dict значений dict для создания нового результата - PullRequest
0 голосов
/ 10 июля 2020

Я работаю над набором данных dict of dict:

data = {'box_1': {'total_packets': 20,
  'packet_loss': 0.32,
  'network_loss': 0.11,
  'full_packets': [0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1],
  'full_network': [0.77118516, 0.15721157, 0.99284172, 0.64352685, 0.43893093,
         0.90650645, 0.31344131, 0.98757972, 0.67239033, 0.45789615,
         0.14901635, 0.86344737, 0.46589434, 0.66976324, 0.19622047,
         0.38090317, 0.76307877, 0.26002821, 0.20494155, 0.84978815],
  'true_packets': [0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0]},
 'box_2': {'total_packets': 20,
  'packet_loss': 0.12,
  'network_loss': 0.11,
  'full_packets': [0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1],
  'full_network': [0.05200178, 0.27056008, 0.10674939, 0.78031958, 0.18292721,
         0.52281292, 0.94423851, 0.07988127, 0.6556706 , 0.82108989,
         0.13918205, 0.23900761, 0.45053918, 0.80958751, 0.21787875,
         0.38729694, 0.64058867, 0.35293909, 0.3345066 , 0.52221203],
  'true_packets': [0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0]},
 'box_3': {'total_packets': 20,
  'packet_loss': 0.62,
  'network_loss': 0.11,
  'full_packets': [1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0],
  'full_network': [0.65296846, 0.79348183, 0.30903056, 0.44789374, 0.63215569,
         0.2749674 , 0.21142709, 0.77792007, 0.70627136, 0.44096512,
         0.1406084 , 0.92678541, 0.36632565, 0.24307549, 0.22864354,
         0.91516214, 0.7331007 , 0.66654516, 0.32463232, 0.35959552],
  'true_packets': [0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0]}}

Ожидаемый результат:

     packets    box  true_value
0   0.771185  box_1           0
1   0.793482  box_3           1
2   0.309031  box_3           0
3   0.447894  box_3           1
4   0.632156  box_3           0
5   0.274967  box_3           0
6   0.211427  box_3           0
7   0.777920  box_3           1
8   0.672390  box_1           1
9   0.440965  box_3           1
10  0.140608  box_3           0
11  0.239008  box_2           1
12  0.366326  box_3           1
13  0.243075  box_3           1
14  0.217879  box_2           0
15  0.915162  box_3           0
16  0.733101  box_3           0
17  0.352939  box_2           0
18  0.324632  box_3           1
19  0.359596  box_3           0

Лог c за этим:

У меня много ящиков в формате dict, в каждом поле 'full_packets' и 'true_packets', 'true_packets' всегда одинаковы в каждая коробка. Я должен сравнить каждую коробку 'full_packets' с 'true_packets' и если 'full_packets' и 'true_packets' значение равно затем возьмите этот индекс из этого поля 'full_network'.

Пример:

network_a = [1,0,0,1]
data_a    = [11,22,33,44]
loss      = 0.2

network_b = [1,1,0,1]
data_b    = [111,222,333,444]
loss      = 0.1

true_values = [1,1,1,1]

Теперь сначала отсортируйте значения на основе потерь, а затем сравните network_a с true_values:

# creating a blank result same len of true values
result = ['blank','blank', 'blank', 'blank']

network_a  == true_values
[1,0,0,1]  == [1,1,1,1]

, как вы можете видеть, индекс 0th, 4th одинаковы, поэтому я возьму 0th и 4th из data_a и сохранить в result сейчас обновлено result будет:

result = [11, 'blank', 'blank', 44]

Сейчас сравниваю network_b == true_values:

network_b  == true_values
[1,1,0,1]  == [1,1,1,1]

Вот противоречие, поскольку 0th, 1th, 4th одинаковы, а в network_a также есть 0th и 4th одинаковы, но я не буду менять значение в result из 0th и 4th, потому что я отдаю приоритет большему ущербу. network_a потери больше, поэтому я оставлю 0th и 4th из network_a и 1st из network_b s data_b

поэтому обновленный *result* будет:

result = [11, 222, 'blank', 44]

Поскольку нет индекса *3rd*, одинакового ни в network_a, ни в network_b, я оставлю только 'blank' .

То, что я пробовал:

from collections import OrderedDict
import pandas as pd

# sorting based on packet loss
od = OrderedDict(sorted(data.items(), key=lambda x: x[1]['packet_loss'], reverse=True))

# seprating full packets, full networks and true packets
full_packets = {}
full_network = {}
true_packets = []

for model_name, model_result in od.items():
    full_packets[model_name] = model_result['full_packets']
    full_network[model_name]    = model_result['full_network']
    true_packets.append(model_result['true_packets'])
    
    
# creating blank true packets for filling it later ( after comparison)
final_result = ['blank'] * len(true_packets[0])

# checking if which true_packets are same in each box's full_packets 
for m, n in full_packets.items():
    for k in range(len(n)):
        full_pack = n[k]
        true_pack = true_packets[0][k]
        if full_pack ==  true_pack:
            if final_result[k] == 'blank':
                final_result[k] = m
                

final_packets = ['blank'] * len(true_packets[0])

# Now those packets's index which are same or equal to true packets taking those index from their full_network data
for m in range(len(true_packets[0])):
    
    meta_data   = final_result[m]
    if meta_data in full_network:
        final_packets[m] = full_network[meta_data][m]

combined_data = list(zip(final_packets,final_result,true_packets[0]))
df = pd.DataFrame(combined_data, columns=['packets', 'box', 'true_value'])

результат:

     packets    box  true_value
0   0.771185  box_1           0
1   0.793482  box_3           1
2   0.309031  box_3           0
3   0.447894  box_3           1
4   0.632156  box_3           0
5   0.274967  box_3           0
6   0.211427  box_3           0
7   0.777920  box_3           1
8   0.672390  box_1           1
9   0.440965  box_3           1
10  0.140608  box_3           0
11  0.239008  box_2           1
12  0.366326  box_3           1
13  0.243075  box_3           1
14  0.217879  box_2           0
15  0.915162  box_3           0
16  0.733101  box_3           0
17  0.352939  box_2           0
18  0.324632  box_3           1
19  0.359596  box_3           0

Он работает, но я ищу совет, как улучшить производительность этот код? Какое изящное решение этой проблемы?

Ответы [ 2 ]

0 голосов
/ 10 июля 2020

Вот простое решение:

_DATA = {'box_1': {'total_packets': 20,
  'packet_loss': 0.32,
  'network_loss': 0.11,
  'full_packets': [0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1],
  'full_network': [0.77118516, 0.15721157, 0.99284172, 0.64352685, 0.43893093,
         0.90650645, 0.31344131, 0.98757972, 0.67239033, 0.45789615,
         0.14901635, 0.86344737, 0.46589434, 0.66976324, 0.19622047,
         0.38090317, 0.76307877, 0.26002821, 0.20494155, 0.84978815],
  'true_packets': [0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0]},
 'box_2': {'total_packets': 20,
  'packet_loss': 0.12,
  'network_loss': 0.11,
  'full_packets': [0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1],
  'full_network': [0.05200178, 0.27056008, 0.10674939, 0.78031958, 0.18292721,
         0.52281292, 0.94423851, 0.07988127, 0.6556706 , 0.82108989,
         0.13918205, 0.23900761, 0.45053918, 0.80958751, 0.21787875,
         0.38729694, 0.64058867, 0.35293909, 0.3345066 , 0.52221203],
  'true_packets': [0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0]},
 'box_3': {'total_packets': 20,
  'packet_loss': 0.62,
  'network_loss': 0.11,
  'full_packets': [1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0],
  'full_network': [0.65296846, 0.79348183, 0.30903056, 0.44789374, 0.63215569,
         0.2749674 , 0.21142709, 0.77792007, 0.70627136, 0.44096512,
         0.1406084 , 0.92678541, 0.36632565, 0.24307549, 0.22864354,
         0.91516214, 0.7331007 , 0.66654516, 0.32463232, 0.35959552],
  'true_packets': [0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0]}}


def _f(data):
    # Sort boxes by packet loss
    boxes = sorted(data.keys(),
                   key=lambda box_name: data[box_name]['packet_loss'])
    result = None
    for box_name in boxes:
        box_data = data[box_name]
        full_packets = box_data['full_packets']
        true_packets = box_data['true_packets']
        all_packets = box_data['full_network']
        if result is None:
            # Initialize result
            result = [None] * len(true_packets)

        for tp_index in range(len(true_packets)):
            if true_packets[tp_index] != full_packets[tp_index]:
                continue

            result[tp_index] = {
                'packet': all_packets[tp_index],
                'box': box_name,
                'true_value': true_packets[tp_index],
            }
    return result


packets = _f(_DATA)
print('Total packets: {}'.format(len(packets)))
print('')
for packet in packets:
    if packet is None:
        continue

    print(packet['packet'], packet['box'], packet['true_value'])

Вывод:

Total packets: 20

0.77118516 box_1 0
0.79348183 box_3 1
0.30903056 box_3 0
0.44789374 box_3 1
0.63215569 box_3 0
0.2749674 box_3 0
0.21142709 box_3 0
0.77792007 box_3 1
0.67239033 box_1 1
0.44096512 box_3 1
0.1406084 box_3 0
0.23900761 box_2 1
0.36632565 box_3 1
0.24307549 box_3 1
0.21787875 box_2 0
0.91516214 box_3 0
0.7331007 box_3 0
0.35293909 box_2 0
0.32463232 box_3 1
0.35959552 box_3 0
0 голосов
/ 10 июля 2020

РЕДАКТИРОВАТЬ: Я исправил свой ответ. Теперь мое решение должно делать то, что требуется.

Вот возможное решение.

import pandas as pd
from collections import OrderedDict

size = 20
max_vals = [(-1, "blank", "blank")]*size
od = OrderedDict(sorted(data.items(), key=lambda x: x[1]['packet_loss'], reverse=True))

for box in od:
    max_vals = list(map(lambda x, y, z, m: (z,box,x) if x==y and m[0] == -1 else m, 
                          data[box]['full_packets'], 
                          data[box]['true_packets'], 
                          data[box]['full_network'],
                          max_vals))

df = pd.DataFrame(max_vals, columns=['packets', 'box', 'true_value'])
print(df)

Результат:

     packets    box  true_value
0   0.771185  box_1           0
1   0.793482  box_3           1
2   0.309031  box_3           0
3   0.447894  box_3           1
4   0.632156  box_3           0
5   0.274967  box_3           0
6   0.211427  box_3           0
7   0.777920  box_3           1
8   0.672390  box_1           1
9   0.440965  box_3           1
10  0.140608  box_3           0
11  0.239008  box_2           1
12  0.366326  box_3           1
13  0.243075  box_3           1
14  0.217879  box_2           0
15  0.915162  box_3           0
16  0.733101  box_3           0
17  0.352939  box_2           0
18  0.324632  box_3           1
19  0.359596  box_3           0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...