Подсчет нескольких входных данных json python

#python #json #formatting

Вопрос:

Я получаю такой ввод:

input 1:

 {

"name": "Ben",
"description": "Ben",
"attributes": [
    {
    "type": "Background",
    "value": "Default"
    },
    {
    "type": "Hair-color",
    "value": "Brown"
    }
]
}

 

input 2

 {

"name": "Ice",
"description": "Ice",
"attributes": [
    {
    "type": "Background",
    "value": "Green"
    },
    {
    "type": "Hair-color",
    "value": "White"
    }
]
}

 

input 3

 {

"name": "Itay",
"description": "Itay",
"attributes": [
    {
    "type": "Background",
    "value": "Default"
    },
    {
    "type": "Hair-color",
    "value": "Brown"
    }
]
}

 

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

Допустим, в этих примерах у нас есть 2 объекта, у которых по умолчанию есть фон, тогда я хочу, чтобы их количество было примерно таким:

 Backround default count=2
hair-color brown = 2
background green = 1
hair-color white = 1
 

Мне нужен наиболее эффективный код, потому что в коде есть и другие аспекты, кроме того, он будет выполняться на тысячах запросов, а не только на двух, поэтому его тоже нужно запускать в хорошие времена 😀
Мой код до сих пор:

 import requests
import json
from collections import Counter
from collections import defaultdict
from time import sleep


attributes = []
test_dict = defaultdict(list)

for i in range(min_id, max_id 1):
    api = 'api/v1/test/{}'.format(i)
    response = requests.get(api)

    item_dict = json.loads(response.text)

    for item in item_dict['attributes']:
        attributes.append(item["trait_type"]) if item["trait_type"] not in attributes else attributes
        test_dict[item["trait_type"]].append(item["value"])
    sleep(0.02)

for attribute in attributes:
    print(attribute)
    print(Counter(test_dict[attribute]))
 

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

1. Что произошло, когда вы попытались это сделать? Как далеко вы продвинулись? В чем была проблема?

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

3. поделитесь своим рабочим кодом

4. @Sabil у меня не так много рабочего кода, в основном это база взаимодействия с API. То, что я собираюсь сделать, — это создать словарь, подобный этому: {backround: default, count: 2} Но это может усложнить дальнейшее кодирование. В конце концов, я хочу рассчитать общее количество объектов (в нашем случае 3) и разделить каждое значение на общее, чтобы увидеть, какой процент от общего количества значений это.

5. Я просто обновляю свой ответ, надеюсь, что он решит все ваши проблемы, включая расчет коэффициента. 🙂

Ответ №1:

Это должно сработать для вас:

 def constract_data(data_dict):
    output = []
    total_count = 0

    for data in data_dict:
        attributes = data["attributes"]
        for attribute in attributes:
            total_count  = 1
            dict_key = attribute["type"].lower()
            dict_value = attribute["value"].lower()
            dict_index = [index for index, data in enumerate(output) if data.get(dict_key, "") == dict_value]

            if dict_index:
                output[dict_index[0]]['count']  = 1
            else:
                atb_dict = {dict_key: dict_value, 'count': 1}
                output.append(atb_dict)

    return output, total_count

def calculate_occurrence_ratio(data_dict, total_count):
    for index, data in enumerate(data_dict):
        count = data.get('count', 0)
        ratio = round(((count / total_count) * 100), 2)
        data['ratio'] = f'{ratio}%'

    return data_dict

data_dict = [
   {
      "name":"Ice",
      "description":"Ice",
      "attributes":[
         {
            "type":"Background",
            "value":"Green"
         },
         {
            "type":"Hair-color",
            "value":"White"
         }
      ]
   },
   {
      "name":"Ben",
      "description":"Ben",
      "attributes":[
         {
            "type":"Background",
            "value":"Default"
         },
         {
            "type":"Hair-color",
            "value":"Brown"
         }
      ]
   },
   {
      "name":"Itay",
      "description":"Itay",
      "attributes":[
         {
            "type":"Background",
            "value":"Default"
         },
         {
            "type":"Hair-color",
            "value":"Brown"
         }
      ]
   }
]

output_data, total_count = constract_data(data_dict)

output_data = calculate_occurrence_ratio(output_data, total_count)

print(output_data)

 

Выход:

 [{'background': 'green', 'count': 1, 'ratio': '16.67%'}, {'hair-color': 'white', 'count': 1, 'ratio': '16.67%'}, {'background': 'default', 'count': 2, 'ratio': '33.33%'}, {'hair-color': 'brown', 'count': 2, 'ratio': '33.33%'}]
 

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

1. Как вы думаете, с каким результатом будет проще работать? Твое или это: {'background': {'green': 1, 'default': 2}, 'hair-color': {'white': 1, 'brown': 2}}

2. Это зависит от того, каким будет результат вашего желания?

3. В общем, что я хочу сделать, так это дать каждой черте оценку. Затем, если у пользователя есть определенная черта, дайте ему оценку. Поэтому в основном я хочу рассчитать редкость появления каждого пользователя с помощью оценки. Допустим, оценка за то, что цвет волос белый, равна 100, Ice получит 100 очков.

4. Ооо, тогда я должен обновить свой ответ в соответствии с вашими требованиями. 🙂

5. Хорошо, потрясающе, тай, и извини за всю суету 😀 Твой ответ потрясающий, и он все прекрасно просчитывает. тай очень сильно 😀

Ответ №2:

это решение будет работать для вас:

 list_data = [
{
"name": "Ice",
"description": "Ice",
"attributes": [
    {
    "type": "Background",
    "value": "Green"
    },
    {
    "type": "Hair-color",
    "value": "White"
    },
    {
    "type": "other",
    "value": "White"
    }
]
},
{

"name": "Ben",
"description": "Ben",
"attributes": [
    {
    "type": "Background",
    "value": "Default"
    },
    {
    "type": "Hair-color",
    "value": "Brown"
    }
]
},{

"name": "Itay",
"description": "Itay",
"attributes": [
    {
    "type": "Background",
    "value": "Default"
    },
    {
    "type": "Hair-color",
    "value": "Brown"
    }
]
},
]
output = {}
all_count = {}
for user in list_data:
    data = user["attributes"]
    for dat in data:
        typeu = dat["type"]
        if typeu not in all_count:
            all_count[typeu]=1
        else:
            all_count[typeu] =1

for user in list_data:
    data = user["attributes"]
    for dat in data:
        typeu = dat["type"]
        if typeu not in output:
            output[typeu]={}
        if dat["value"] not in output[typeu]:
            output[typeu][dat["value"]] = "1 with: {}%".format(int(1/all_count[typeu]*100))
        else:
            count = int(output[typeu][dat["value"]][0]) 1
            output[typeu][dat["value"]] = str(count) " with: {}%".format(int(count/all_count[typeu]*100))
print(output)
 

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

1. Как я уже говорил в посте, иногда атрибутами будут не только фон и цвет волос. Сценарий должен идентифицировать их самостоятельно…

2. хорошо, я отредактировал это

3. Как вы думаете, есть ли способ также рассчитать вероятность того, что это произойдет? Так что в основном просто разделите количество каждого элемента на общее количество пользователей: Backround default:2 66% of it occuring

4. я отредактировал его. не могли бы вы, пожалуйста, отметить это как решение?

5. Когда я помещаю это в свой код, некоторые атрибуты отображаются как 100%, некоторые нет, и общий процент не составляет 100% пример: {'background': {'crisp green': '1 Ratio: 100%', 'dashing purple': '2 Ratio: 66%', 'spiffy blue': '1 Ratio: 25%', 'dapper cyan': '2 Ratio: 33%'}

Ответ №3:

Вот еще один подход:

 from collections import defaultdict
data_dict = [
   {
      "name":"Ice",
      "description":"Ice",
      "attributes":[
         {
            "type":"Background",
            "value":"Green"
         },
         {
            "type":"Hair-color",
            "value":"White"
         }
      ]
   },
   {
      "name":"Ben",
      "description":"Ben",
      "attributes":[
         {
            "type":"Background",
            "value":"Default"
         },
         {
            "type":"Hair-color",
            "value":"Brown"
         }
      ]
   },
   {
      "name":"Itay",
      "description":"Itay",
      "attributes":[
         {
            "type":"Background",
            "value":"Default"
         },
         {
            "type":"Hair-color",
            "value":"Brown"
         }
      ]
   }
]

out = defaultdict(lambda: defaultdict(int))
tot_count = defaultdict(int)
for data in data_dict:
    for attri in data['attributes']:
        tot_count[attri['type']] =1
        out[attri['type']][attri['value']] =1
for k, v in out.items():
    for k1, v1 in v.items():
        print (f'{k.lower()} {k1} count={v1} ratio={int(v1*100/tot_count[k])}%')
 

Выход:

 background Green count=1 ratio=33%
background Default count=2 ratio=66%
hair-color White count=1 ratio=33%
hair-color Brown count=2 ratio=66%