[英]Find the average of inner dictionary keys after grouping outer key
我有一個嵌套字典,例如;
dictionary = {'cat_1' : {'age' : 5, 'height' : 15}, 'cat_2' : {'age' : 1, 'height' : 7}, 'dog_1' : {'age' : 13, 'height' : 20}, 'dog_2' : {'age' : 9, 'height' : 18}}
我想通過對外部id鍵進行分組(使用類似key.split('_')[0]
)來查找每種動物類型的內部字典鍵的平均值。
怎么樣,它使用Pandas
import pandas as pd
df = pd.DataFrame.from_records(dictionary)
cat_1 cat_2 dog_1 dog_2
age 5 1 13 9
height 15 7 20 18
df = df.T.reset_index()
index age height
0 cat_1 5 15
1 cat_2 1 7
2 dog_1 13 20
3 dog_2 9 18
df['index'] = [elem.split('_',1)[0] for elem in df['index']]
index age height
0 cat 5 15
1 cat 1 7
2 dog 13 20
3 dog 9 18
df.groupby('index').mean().T
index cat dog
age 3 11
height 11 19
如果輸出需要是字典,那么:
df.groupby('index').mean().T.to_dict()
{'cat': {'age': 3, 'height': 11}, 'dog': {'age': 11, 'height': 19}}
您可以使用itertools
模塊中的sum()
和groupby
itertools
:
from itertools import groupby
a = {'cat_1' : {'age' : 5, 'height' : 15}, 'cat_2' : {'age' : 1, 'height' : 7}, 'dog_1' : {'age' : 13, 'height' : 20}, 'dog_2' : {'age' : 9, 'height' : 18}}
animals, final = {}, {}
for k,v in groupby(sorted(a.items(), key=lambda x:x[0].split('_')[0]), lambda x: x[0].split('_')[0]):
animals[k] = [j for _, j in list(v)]
for k in animals:
final[k] = {"height": sum(j["height"] for j in animals[k])/len(animals[k]),
"age": sum(j["age"] for j in animals[k])/len(animals[k])}
print(final)
輸出:
{'cat': {'height': 11.0, 'age': 3.0}, 'dog': {'height': 19.0, 'age': 11.0}}
這樣的事可能會:
dictionary = {'cat_1' : {'age' : 5, 'height' : 15}, 'cat_2' : {'age' : 1, 'height' : 7}, 'dog_1' : {'age' : 13, 'height' : 20}, 'dog_2' : {'age' : 9, 'height' : 18}}
cats = dict((k, v) for k, v in dictionary.items() if k.startswith("cat"))
cat_count = len(cats)
cat_average_ages = sum([cats[k]["age"] for k in cats]) / cat_count
cat_average_heights = sum([cats[k]["height"] for k in cats]) / cat_count
您可以只為狗復制它或創建一個返回平均值的函數,具體取決於您有多少種不同的動物:
def find_average_values(animals_dict, animal_name="cat"):
animals = dict((k, v) for k, v in dictionary.items() if k.startswith(animal_name))
animal_count = len(animals)
animal_average_ages = sum([animals[k]["age"] for k in animals]) / animal_count
animal_average_heights = sum([animals[k]["height"] for k in animals]) / animal_count
return {"age": animal_average_ages, "height": animal_average_heights}
dog_averages = find_average_values(dictionary, "dog")
使用itertools.groupby
和collections.defaultdict
另一個答案。 有一個額外的好處,不需要知道你的內部字典鍵。
from itertools import groupby
from collections import defaultdict
d = {'cat_1' : {'age' : 5, 'height' : 15}, 'cat_2' : {'age' : 1, 'height' : 7}, 'dog_1' : {'age' : 13, 'height' : 20}, 'dog_2' : {'age' : 9, 'height' : 18}}
res = defaultdict(lambda : defaultdict(int))
# Group inner dicts by key
for k, g in groupby(d.items(), lambda t: t[0].split('_')[0]):
for _, inner in g:
# total the values
for key, value in inner.items():
res[k][key] += value
# for each key average by the length of the dict
res[k] = { _k : _v / len(inner) for _k, _v in res[k].items() }
另一個不需要您手動指定密鑰的選項是:
from collections import Counter, defaultdict
from itertools import groupby, chain
dictionary = {'cat_1' : {'age' : 5, 'height' : 15},
'cat_2' : {'age' : 1, 'height' : 7},
'dog_1' : {'age' : 13, 'height' : 20},
'dog_2' : {'age' : 9, 'height' : 18}}
animals_grouped = groupby(sorted(dictionary.items(),
key=lambda x: x[0].split('_')[0]),
key=lambda x: x[0].split('_')[0])
animals_data_average = defaultdict(dict)
for animal in animals_grouped:
animal_data_list = list(chain.from_iterable(list(animal_data[1].items()) for animal_data in animal[1]))
animal_key_counter = Counter([animal_data[0] for animal_data in animal_data_list])
for data_key in animal_key_counter:
animals_data_average[animal[0]][data_key] = sum([animal_data[1] for animal_data in animal_data_list if animal_data[0] == data_key]) / animal_key_counter[data_key]
print(dict(animals_data_average))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.