Создание словаря - PullRequest
       0

Создание словаря

0 голосов
/ 19 июня 2020

У меня есть некоторые проблемы с построением следующих значений:

my_dict={'word1': ['31', '131', '2'], 'word2': ['42', '33', '154', '21']}

Я сделал

plt.bar(my_dict.keys(), my_dict.values(), color='g')

, но получил эту ошибку:

TypeError: ufun c 'add' не содержал al oop с типами соответствия подписи dtype ('

Затем я попытался с

plt.plot(*zip(*sorted(my_dict.items())))
plt.show()

, но я получил эту другую ошибку :

TypeError: unhashable type: 'list'

Меня интересует частота.

Что мне делать, чтобы это исправить?

Из исходного набора данных (так как у меня есть ошибка для репликации кода):

my_dict = defaultdict(list)

print({ k : v for k, v in my_dict.items() })

вывод:

{'word1': ['122', '121.2', '132', '132', '144', '144.5', '144', '150', '150,5', '150,5', '150,5'], 'word2': ['230', '230', '230', '230'], 'word3': ['542', '542', '540'], 'word4': ['134', '134']}

Мне нужно было бы построить график частоты значений в каждом слове (например, для слова 1 у меня должна быть частота 2 для 132 и 144, затем 3 для 150,5, 1 для всех остальных значений).

Ответы [ 2 ]

2 голосов
/ 19 июня 2020

Вот как это можно сделать с помощью matplotlib:

import matplotlib.pyplot as plt
from numpy import random

mydict={'word1': ['122', '121.2', '132', '132', '144', '144.5', '144', '150', '150,5', '150,5', '150,5'], 'word2': ['230', '230', '230', '230'], 'word3': ['542', '542', '540'], 'word4': ['134', '134']}


for k,l in mydict.items():
    labeled = False
    c=random.rand(3,)
    for v in l:
        if labeled:
            plt.bar(v,len([d for d in l if d==v]),color=c)
        else:
            plt.bar(v,len([d for d in l if d==v]),label=k,color=c)
            labeled = True

plt.legend()
plt.show()

введите описание изображения здесь

1 голос
/ 19 июня 2020

Используйте pandas и zip_longest

  • Pandas требует, чтобы столбцы имели одинаковую длину, поэтому zip_longest заполнит пробелы None.
  • Существует несколько вариантов формирования данных в зависимости от того, как вы хотите их построить.
import pandas as pd
from itertools import zip_longest
import matplotlib.pyplot as plt

# data
d = {'word1': ['122', '121.2', '132', '132', '144', '144.5', '144', '150', '150.5', '150.5', '150.5'], 'word2': ['230', '230', '230', '230'], 'word3': ['542', '542', '540'], 'word4': ['134', '134']}

# since the values lists are uneven
cols = d.keys()
val = list(zip_longest(*d.values()))

# dataframe
df = pd.DataFrame(val, columns=cols, dtype=float)

    word1  word2  word3  word4
0   122.0  230.0  542.0  134.0
1   121.2  230.0  542.0  134.0
2   132.0  230.0  540.0    NaN
3   132.0  230.0    NaN    NaN
4   144.0    NaN    NaN    NaN
5   144.5    NaN    NaN    NaN
6   144.0    NaN    NaN    NaN
7   150.0    NaN    NaN    NaN
8   150.5    NaN    NaN    NaN
9   150.5    NaN    NaN    NaN
10  150.5    NaN    NaN    NaN

график с аннотациями

ax = df.plot.bar()

f = [df[c].value_counts().to_dict() for c in df.columns]  # list of list of value counts
f = dict(kv for d in f for kv in d.items())  # this will break if the values for each word aren't unique

for p in ax.patches:

    if p.get_height() > 0:

        # add value at top of bar
        ax.annotate(format(p.get_height(), '.1f'),
                    (p.get_x() + p.get_width() / 2., p.get_height() + 10),
                    ha = 'center', va = 'center', fontsize=9, rotation=90,
                    xytext = (0, 10), textcoords = 'offset points')

        # add frequency of value at center of bar
        ax.annotate(format(f[p.get_height()], '.0f'),
            (p.get_x() + p.get_width() / 2., p.get_height() / 2),
            ha = 'center', va = 'center', fontsize=9, rotation=0,
            xytext = (0, 10), textcoords = 'offset points')

enter image description here

tdf = df.T  # transpose dataframe df

ax = tdf.plot.bar()

f = [df[c].value_counts().to_dict() for c in df.columns]  # list of list of value counts
f = dict(kv for d in f for kv in d.items())  # this will break if the values for each word aren't unique

for p in ax.patches:

    if p.get_height() > 0:

        # add value at top of bar
        ax.annotate(format(p.get_height(), '.1f'),
                    (p.get_x() + p.get_width() / 2., p.get_height() + 10),
                    ha = 'center', va = 'center', fontsize=9, rotation=90,
                    xytext = (0, 10), textcoords = 'offset points')

        # add frequency of value at center of bar
        ax.annotate(format(f[p.get_height()], '.0f'),
            (p.get_x() + p.get_width() / 2., p.get_height() / 2),
            ha = 'center', va = 'center', fontsize=9, rotation=0,
            xytext = (0, 10), textcoords = 'offset points')

enter image description here

Без аннотаций

  • Раскрашивание hue помещает полосы смещены от центра на основе количества уникальных значений в столбце, используемых в этом случае hue, word.
    • В приведенном ниже примере все четыре слова содержат значение 150.5, поэтому вы можете видеть их сгруппированными на графике.
  • Полосы горизонтальны для размещения большое количество значений.
    • Просто увеличьте figsize высоту.
import seaborn as sns

d = {'word1': ['122', '121.2', '132', '132', '144', '144.5', '144', '150', '150.5', '150.5', '150.5'], 'word2': ['230', '230', '230', '230', '150.5'], 'word3': ['542', '542', '540', '150.5'], 'word4': ['134', '134', '150.5']}

cols = d.keys()
val = list(zip_longest(*d.values()))

# dataframe
df = pd.DataFrame(val, columns=cols, dtype=float)

# convert from wide to long
df['id'] = df.index
dfl = pd.wide_to_long(df, stubnames='word', j='x', i='id').reset_index().rename(columns={'word': 'v', 'x': 'word'}).dropna()

# groupby for frequency counts
dflg = dfl.groupby('word').agg({'v': 'value_counts'}).rename(columns={'v': 'freq_count'}).reset_index().sort_values('v')

# plot
plt.figure(figsize=(6, 10))
p = sns.barplot(y='v', x='freq_count', data=dflg, hue='word', orient='h')

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...