4.1. Análise dos dados de periódicos da Hemeroteca Digital Brasileira da Biblioteca Nacional#
Os dados foram disponibilizados para pesquisa pela equipe da BNDigital em formato xml. O arquivo foi exportado da base do sistema de periódicos digitalizados e se encontra no padrão MARCXML (MAchine-Readable Cataloging XML).
O arquivo pode ser acessado aqui.
Agradeço a Vinicius Pontes Martins do Setor de Gestão de Programas e Inovação (SGPI) e toda a equipe da BNDigital pela disponibilização dos dados.
Analisando e Filtrando o xml#
Aqui vamos realizar realizar o parse dos dados contidos no arquivo xml e filtrar os dados que serão utilizados para análise.
Utilizaremos a biblioteca xml.etree.ElementTree
para realizar o parse do arquivo xml. A biblioteca é nativa do Python e não necessita de instalação.
# importar bibliotecas
import xml.etree.ElementTree as ET
# ler arquivo xml
tree = ET.parse('../../../data/bndbr/exp_per_marcxml.xml')
Após realizarmos o parse do ficheiro, podemos contar quantos registros exixtem na àrvore de elementos:
# contar número de registros
root = tree.getroot()
print(len(root))
7685
Subcampos utilizados#
Após a leitura do arquivos, selecionei sete subcampos para análise (serão listadas a tag e o subcampo de acordo com a estrutura do xml):
tag 245; subcampo a: Título do periódico
tag 245; subcampo b: Subtítulo do periódico
tag 260; subcampo a: Local de publicação
tag 260; subcampo b: Editora
tag 260; subcampo c: Período de publicação
tag 310; subcampo a: Periodicidade da publicação
tag 546; subcampo a: Idioma da publicação
A seleção desses elementos buscou possibilitar a comparação com os dados disponibilizados pela BND-PT, conforme descrito no tópico 4.1.
Vamos criar um ficheiro csv com os dados selecionados. Para isso, vamos utilizar a biblioteca csv
do Python.
Primeiro criamos uma função para encontrar os subcampos desejados:
# função para encontrar o valor de um campo
def find_value(record, tag,code):
return record.find(f"./datafield[@tag='{tag}']/subfield[@code='{code}']")
Em seguida, criamos o ficheiro csv e escrevemos os dados:
# criar um csv com os dados selecionados
import csv
with open('../../../data/complete_data.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL)
writer.writerow(['title', 'subtitle', 'place', 'period', 'publisher', 'periodicity', 'language'])
for record in root:
title = find_value(record, '245', 'a')
subtitle = find_value(record, '245', 'b')
place = find_value(record, '260', 'a')
period = find_value(record, '260', 'c')
publisher = find_value(record, '260', 'b')
periodicity = find_value(record, '310', 'a')
language = find_value(record, '546', 'a')
if title is not None:
title = title.text
if subtitle is not None:
subtitle = subtitle.text
if place is not None:
place = place.text
if period is not None:
period = period.text
if publisher is not None:
publisher = publisher.text
if periodicity is not None:
periodicity = periodicity.text
if language is not None:
language = language.text
writer.writerow([title, subtitle, place, period, publisher, periodicity, language])
Apresentação dos dados#
A partir do ficheiro csv gerado na célula anterior, vamos apresentar os dados da HDB buscando uma compreensão geral do seu acervo de periódicos digitalizados.
Os dados serão analisados com a biblioteca pandas
e apresentados com a biblioteca plotly
.
# importar bibliotecas
import pandas as pd
import plotly.express as px
import plotly.io as pio
import plotly.offline as py
pio.renderers.default = "notebook"
Dados gerais do acervo#
Vamos criar um dataframe com os dados do csv e apresentar sua estrutura e informações gerais.
# importar dataset e criar dataframe
df = pd.read_csv('../../../data/complete_data.csv', encoding='utf-8')
Para termos uma ideia geral do dataframe, vamos ver as primeiras 10 linhas do dataframe:
df.head()
title | subtitle | place | period | publisher | periodicity | language | |
---|---|---|---|---|---|---|---|
0 | O Abolicionista Paraense | NaN | Belém, PA | 1883- | Typ. da Provincia do Para | Semanal | por |
1 | O Abolicionista | propriedade de uma associação | São Luis, MA | 1885 | Typ. do Abolicionista | NaN | por |
2 | O Academico | periodico scientifico, litterario e especialme... | Rio de Janeiro, RJ | 1855- | Typ. Fluminense, de D.L. dos Santos | NaN | por |
3 | A Actualidade | orgao do Partido Liberal | Ouro Preto, MG | 1878-[1882] | Typ. de Jose Egydio da Silca Campos | 3 vezes por semana | NaN |
4 | A Actualidade | periodico imparcial, litterario, critico e not... | Maranhão | 1900- | Typ. de Antonio Pereira Ramos d'Almeida e C. S... | 3 vezes por mês | por |
O dataframe é composto pelas seguintes colunas:
# mostrar colunas em lista
df.columns.tolist()
['title',
'subtitle',
'place',
'period',
'publisher',
'periodicity',
'language']
# contar número de registros
df.count()
title 7685
subtitle 3666
place 7608
period 7265
publisher 5675
periodicity 5901
language 6614
dtype: int64
Percebemos que o dataframe conta com 7685 periódicos. Os dados das demais colunas variam, e as colunas período e local de publicação são as mais completas.
Idiomas#
Vamos contar os idiomas dos periódicos digitalizados, mas primeiro vamos limpar os dados da coluna ‘language’.
# limpar dados de idioma
# lista de termos para substituir
replace_por = ['Texto em português', 'Texto em portugues', 'Português', 'Em português', 'Texto em português e alguns textos em francês']
replace_spa = ['Texto em espanhol', 'esp']
replace_fre = ['Texto em frances']
# substituir termos
df['language'] = df['language'].replace(replace_por, 'por')
df['language'] = df['language'].replace(replace_spa, 'spa')
df['language'] = df['language'].replace(replace_fre, 'fre')
Vamos avaliar quantos registros não possuem idioma definido:
# contar quantos registros não possuem idioma
df['language'].isnull().sum()
1071
# calcular a porcentagem de registros sem idioma
df['language'].isnull().sum() / len(df) * 100
13.936239427456082
Dos 7685 registros, 1071 não possuem idioma definido no dataframe, o que corresponde a 13,93% do total.
Vamos incluir o valor ‘Não definido’ para os registros sem idioma definido:
# incluir valor 'não definido' para registros sem idioma
df['language'] = df['language'].fillna('não definido')
Agora uma contagem dos idiomas dos periódicos será mais precisa:
# criar dataframe com a contagem de idiomas
df_lang = df['language'].value_counts().rename_axis('Idioma').reset_index(name='Quantidade')
df_lang
Idioma | Quantidade | |
---|---|---|
0 | por | 6462 |
1 | não definido | 1071 |
2 | ger | 61 |
3 | ita | 33 |
4 | fre | 27 |
5 | spa | 17 |
6 | eng | 10 |
7 | ara | 2 |
8 | syr | 1 |
9 | yid | 1 |
Em termos de porcentagem, podemos ver que o idioma predominante é o português, com 84% dos periódicos. Em seguida, temos os periódicos sem idioma definido, 13,9%, seguidos de alemão, italiano, francês, espanhol e inglês, cada um com menos de 1% cada.
# porcentagem de idiomas
df['language'].value_counts(normalize=True)
por 0.840859
não definido 0.139362
ger 0.007938
ita 0.004294
fre 0.003513
spa 0.002212
eng 0.001301
ara 0.000260
syr 0.000130
yid 0.000130
Name: language, dtype: float64
# criar função para gerar gráfico de barras
def bar_chart(df, x, y, title, color, range_x, range_y):
fig = px.bar(df, x=x, y=y, title=title, color=color)
fig.update_xaxes(tickangle=45, tickfont=dict(size=10))
if range_x is not None:
fig.update_xaxes(range=[range_x[0], range_x[1]])
if range_y is not None:
fig.update_yaxes(range=[range_y[0], range_y[1]])
fig.update_layout(height=800, width=1200)
return fig
Podemos visualizar de forma mais clara esses dados com um gráfico de barras:
# criar gráfico de barras com os dados de idiomas dos periódicos
fig1 = bar_chart(df_lang, 'Idioma', 'Quantidade', 'Idiomas dos periódicos', 'Idioma', None, None)
fig1
Período de publicação#
Vamos analisar os dados referentes aos períodos de publicação dos periódicos digitalizados. Esses dados possuem algumas características que tornam sua análise mais complexa.
Primeiro, percebemos que existe uma falta de padronização dos dados. Alguns registros possuem apenas o ano de início, outros possuem o ano de início e fim, e esses dados são escritos de formas variadas.
Portanto, primeiramente vou efetuar uma limpeza e padronização dos dados. Para isso, vou excluir caracteres especiais e buscar padronizar os dados para o formato ‘yyyy-yyyy’.
Assim, acredito minimizar os erros de análise e facilitar a visualização dos dados.
# limpar dados do período de publicação usando regex
# excluir [, ], (, ), :
df['period'] = df['period'].replace(to_replace=r'[\[\]\(\):\?]', value='', regex=True)
#substituir ' - ' por '-'
df['period'] = df['period'].replace(to_replace=r' - ', value='-', regex=True)
#substituir ' a ' por '-'
df['period'] = df['period'].replace(to_replace=r' a ', value='-', regex=True)
Para tornar a análise e visualização mais eficiente, vou criar novas colunas para o ano de início e fim dos periódicos.
Caso o registro não possua o ano de fim, vou considerar o ano de início como ano de fim.
# criar coluna com o ano de início da publicação
# se iniciar com dígito, pegar os 4 primeiros caracteres, senão, pegar do 2º ao 5º caractere
df['start_year'] = df['period'].str.extract(r'(\d{4})', expand=False).fillna(df['period'].str[1:5])
# criar coluna com o ano de término da publicação a partir da coluna period
# pegar 4 últimos dígitos que aparecem na coluna period usando regex
df['end_year'] = df['period'].str.extract(r'(\d{4})$', expand=False)
# se 'end_year' for nulo, pegar o ano de início da publicação
df['end_year'] = df['end_year'].fillna(df['start_year'])
Uma última limpeza final, para excluir possíveis caracteres que não sejam dígitos nas colunas de ano de início e fim e inserior o número 0 para os registros que não possuem ano de início e/ou fim.
#converte as colunas para string
df['start_year'] = df['start_year'].astype(str)
df['end_year'] = df['end_year'].astype(str)
# Substitui todos os caracteres que não são dígitos por uma string vazia
df['start_year'] = df['start_year'].replace(to_replace=r'\D', value='', regex=True)
df['end_year'] = df['end_year'].replace(to_replace=r'\D', value='', regex=True)
# substitui os valores vazios por 0
df['start_year'] = df['start_year'].replace(to_replace=r'^\s*$', value='0', regex=True)
df['end_year'] = df['end_year'].replace(to_replace=r'^\s*$', value='0', regex=True)
# converte as colunas para int
df['start_year'] = df['start_year'].astype(int)
df['end_year'] = df['end_year'].astype(int)
Vamos conferir a quantidade de registros por ano de início e fim, lembrando que o número 0 representa os registros que não possuem ano de início e/ou fim:
Primeiro, criar um dataframe com a contagem dos registros por ano de início:
# contar início da publicação
df_bdate = df['start_year'].value_counts().rename_axis('Ano').reset_index(name='quantidade')
# organizar por ano
df_bdate = df_bdate.sort_values(by=['Ano'])
Vamos avaliar os dados iniciais do dataframe para encontrar possíveis erros:
df_bdate.head(10)
Ano | quantidade | |
---|---|---|
0 | 0 | 425 |
181 | 9 | 2 |
200 | 83 | 1 |
210 | 87 | 1 |
199 | 88 | 1 |
196 | 95 | 1 |
208 | 1521 | 1 |
206 | 1691 | 1 |
203 | 1741 | 1 |
201 | 1763 | 1 |
Percemos que 5 registros possuem registros que fogem do oadrão YYYY
e, sendo estatisticamente insignificantes, serão excluídos do dataframe.
# excluir registros com ano entre 2 e 999
df_bdate = df_bdate[(df_bdate['Ano'] < 1) | (df_bdate['Ano'] > 999)]
Faremos o mesmo para final do dataframe:
df_bdate.tail(10)
Ano | quantidade | |
---|---|---|
162 | 2005 | 6 |
186 | 2006 | 2 |
195 | 2007 | 1 |
187 | 2010 | 2 |
209 | 2011 | 1 |
177 | 2012 | 3 |
183 | 2014 | 2 |
213 | 2017 | 1 |
198 | 2021 | 1 |
211 | 2022 | 1 |
Não há erros no fim. Podemos prosseguir para a visualização dos dados.
# excluir registros menor que 1000
df_bdate = df_bdate[df_bdate['Ano'] > 999]
# Criar scatter plot com os dados de datas de publicação com as datas de publicação no eixo Y
fig2 = px.scatter(df_bdate, x='Ano', y='quantidade', title='Datas de início de publicação')
# adcionar mais anos no eixo x
fig2.update_xaxes(range=[1500, 2023])
fig2
Realizaremos os mesmo procedimentos para a coluna do ano de fim:
# contar fim da publicação
df_edate = df['end_year'].value_counts().rename_axis('Ano').reset_index(name='quantidade')
# organizar por ano
df_edate = df_edate.sort_values(by=['Ano'])
df_edate.head(10)
Ano | quantidade | |
---|---|---|
0 | 0 | 425 |
186 | 9 | 2 |
202 | 83 | 1 |
215 | 87 | 1 |
218 | 88 | 1 |
208 | 95 | 1 |
210 | 1521 | 1 |
217 | 1694 | 1 |
216 | 1741 | 1 |
214 | 1767 | 1 |
df_edate.tail(10)
Ano | quantidade | |
---|---|---|
188 | 2016 | 2 |
181 | 2017 | 3 |
180 | 2018 | 3 |
206 | 2019 | 1 |
207 | 2020 | 1 |
193 | 2021 | 2 |
179 | 2022 | 3 |
196 | 2023 | 2 |
205 | 4949 | 1 |
201 | 9924 | 1 |
# excluir registros com ano entre 2 e 999 e acima de 2023
df_edate = df_edate[(df_edate['Ano'] < 1) | (df_edate['Ano'] > 999)]
df_edate = df_edate[df_edate['Ano'] < 2023]
# criar scatter plot com os dados de datas de publicação com as datas de publicação no eixo Y
fig3 = px.scatter(df_edate, x='Ano', y='quantidade', title='Datas de término de publicação')
# adcionar mais anos no eixo x
fig3.update_xaxes(range=[1500, 2023])
# limitar eixo y a 200
fig3.update_yaxes(range=[0, 200])
fig3.show()
# criar um scatter plot com os dados de datas de início e fim de publicação
fig4 = px.scatter(df_bdate, x='Ano', y='quantidade', title='Datas de início e término de publicação')
# adicionar df_edate ao gráfico
fig4.add_scatter(x=df_edate['Ano'], y=df_edate['quantidade'], mode='lines', name='Término de publicação')
# adcionar mais anos no eixo x
fig4.update_xaxes(range=[1500, 2023])
# limitar eixo y entre 0 e 200
fig4.update_yaxes(range=[0, 200])
# mostrar legenda para df_bdate
fig4.update_layout(legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01))
fig4.show()
Vamos calcular a quantidade de publicações por ano de início agrupadas por década (aqui vamos seguir o padrão mais comum no acervo da HDB, 1900 - 1909 corresponde à década de 1900, 1910 - 1919 corresponde à década de 1910, e assim por diante):
# criar coluna com década de início de publicação
df['start_decade'] = df['start_year'].astype(str).str[:3] + '0'
# contar década de início de publicação e csalvar em um dataframe
df_bdecade = df['start_decade'].value_counts().rename_axis('Década').reset_index(name='quantidade')
df_bdecade = df_bdecade.sort_values(by=['Década'])
# tornar a coluna 'Década' em inteiro
df_bdecade['Década'] = df_bdecade['Década'].astype(int)
df_bdecade
Década | quantidade | |
---|---|---|
6 | 0 | 425 |
30 | 1520 | 1 |
29 | 1690 | 1 |
25 | 1740 | 1 |
27 | 1760 | 1 |
22 | 1800 | 2 |
20 | 1810 | 16 |
12 | 1820 | 149 |
8 | 1830 | 387 |
10 | 1840 | 327 |
9 | 1850 | 350 |
5 | 1860 | 497 |
2 | 1870 | 781 |
0 | 1880 | 1277 |
1 | 1890 | 1101 |
3 | 1900 | 530 |
4 | 1910 | 506 |
7 | 1920 | 417 |
11 | 1930 | 304 |
13 | 1940 | 138 |
14 | 1950 | 131 |
17 | 1960 | 84 |
15 | 1970 | 97 |
16 | 1980 | 96 |
18 | 1990 | 31 |
19 | 2000 | 18 |
21 | 2010 | 9 |
24 | 2020 | 2 |
31 | 830 | 1 |
28 | 870 | 1 |
32 | 880 | 1 |
23 | 90 | 2 |
26 | 950 | 1 |
# excluir registros com década menor que 1500 e maior que 2023
df_bdecade = df_bdecade[(df_bdecade['Década'] > 1500) & (df_bdecade['Década'] < 2023)]
# criar um gráfico de barras com os dados de década de início de publicação
fig5 = bar_chart(df_bdecade, 'Década', 'quantidade', 'Décadas de início de publicação (com mais de 1 publicação)', range_x=[1800, 2023], range_y=[0, 1400], color=None)
# adcionar texto nas barras
fig5.update_traces(texttemplate='%{y}', textposition='inside')
fig5.show()
# criar coluna com década de término de publicação
df['end_decade'] = df['end_year'].astype(str).str[:3] + '0'
# contar década de término de publicação e salvar em um dataframe
df_edecade = df['end_decade'].value_counts().rename_axis('Década').reset_index(name='quantidade')
df_edecade = df_edecade.sort_values(by=['Década'])
# tornar a coluna 'Década' em inteiro
df_edecade['Década'] = df_edecade['Década'].astype(int)
df_edecade
Década | quantidade | |
---|---|---|
6 | 0 | 425 |
32 | 1520 | 1 |
28 | 1690 | 1 |
30 | 1740 | 1 |
29 | 1760 | 1 |
27 | 1780 | 1 |
21 | 1810 | 9 |
14 | 1820 | 133 |
8 | 1830 | 375 |
11 | 1840 | 305 |
10 | 1850 | 334 |
5 | 1860 | 470 |
2 | 1870 | 728 |
0 | 1880 | 1284 |
1 | 1890 | 1092 |
3 | 1900 | 542 |
4 | 1910 | 478 |
7 | 1920 | 397 |
9 | 1930 | 353 |
13 | 1940 | 147 |
12 | 1950 | 168 |
17 | 1960 | 108 |
16 | 1970 | 120 |
15 | 1980 | 121 |
18 | 1990 | 35 |
20 | 2000 | 20 |
19 | 2010 | 20 |
22 | 2020 | 8 |
26 | 4940 | 1 |
31 | 830 | 1 |
33 | 870 | 1 |
34 | 880 | 1 |
23 | 90 | 2 |
24 | 950 | 1 |
25 | 9920 | 1 |
# excluir registros com década menor que 1500 e maior que 2023
df_edecade = df_edecade[(df_edecade['Década'] > 1500) & (df_edecade['Década'] < 2023)]
# criar um gráfico de barras com os dados de década de término de publicação
fig6 = bar_chart(df_edecade, 'Década', 'quantidade', 'Décadas de término de publicação (com mais de 1 publicação)', range_x=[1800, 2023], range_y=[0, 1400], color=None)
# adcionar texto nas barras
fig6.update_traces(texttemplate='%{y}', textposition='inside')
fig6.show()
# criar um gráfico de barras com os dados de década de início e término de publicação
fig7 = bar_chart(df_bdecade, 'Década', 'quantidade', 'Décadas de início e término de publicação (com mais de 1 publicação)', range_x=[1800, 2023], range_y=[0, 2600], color=None)
# adcionar texto nas barras
fig7.update_traces(texttemplate='%{y}', textposition='inside')
# adicionar df_edecade ao gráfico
fig7.add_bar(x=df_edecade['Década'], y=df_edecade['quantidade'], name='Término de publicação')
# adcionar texto nas barras de df_edecade
fig7.update_traces(texttemplate='%{y}', textposition='inside')
# mostrar legenda para df_bdecade
fig7.update_layout(legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01))
fig7.show()
Vamos avaliar quantos registros possuem o mesmo ano de início e fim:
# contar quando início e fim da publicação são iguais
df[df['start_year'] == df['end_year']].count()
title 5694
subtitle 2874
place 5626
period 5274
publisher 4155
periodicity 4507
language 5694
start_year 5694
end_year 5694
start_decade 5694
end_decade 5694
dtype: int64
Em 5694 registros, o ano de início da publicação é o mesmo do ano de término, indicando que 7265 periódicos que possuem data registrada no dataframe, apenas 1569 possuem data de início e término diferentes. Isso corresponde a uma porcentagem de 21,6% dos periódicos.
Vamos criar uma nova coluna contando a quantidade de anos presentes no acervo de cada periódico:
# calcular a diferença entre início e fim da publicação
df['diff'] = df['end_year'] - df['start_year']
# listar periódicos com maiores diferenças entre início e fim da publicação
df.sort_values(by='diff', ascending=False).head(20)
title | subtitle | place | period | publisher | periodicity | language | start_year | end_year | start_decade | end_decade | diff | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
5880 | O Povo | orgam do Partido Popular | Pitangui, MG | 19924 | NaN | Semanal | não definido | 1992 | 9924 | 1990 | 9920 | 7932 |
4303 | O Abaete : jornal noticioso a servico do progr... | NaN | Abaeté, MG | 1948-4949 | [s.n.] | NaN | por | 1948 | 4949 | 1940 | 4940 | 3001 |
2489 | Diário de Pernambuco | NaN | Recife, PE | 1825-1984 | Diário de Pernambuco | Diária | não definido | 1825 | 1984 | 1820 | 1980 | 159 |
2286 | Correio Official de Goyaz | NaN | Goiás, GO | 1837-1943 | Typ. Provincial | Desconhecida | por | 1837 | 1943 | 1830 | 1940 | 106 |
3659 | Jornal do Commercio | NaN | Manaus, AM | 1904-2007 | Empresa Jornal do Commercio | Diária | não definido | 1904 | 2007 | 1900 | 2000 | 103 |
3473 | Imprensa e Lei | NaN | Lisboa [Portugal] | 1854-1956 | NaN | Indeterminada | por | 1854 | 1956 | 1850 | 1950 | 102 |
1307 | Almanak do Ministerio da Marinha | NaN | Rio de Janeiro, RJ | 1858-1960 | NaN | Anual | por | 1858 | 1960 | 1850 | 1960 | 102 |
6990 | Revista do Clube de Engenharia | NaN | Rio de Janeiro, RJ | 1887-1989 | O Clube | NaN | por | 1887 | 1989 | 1880 | 1980 | 102 |
770 | A Nova Era | NaN | Aracaju, SE | 1889-1990 | [s.n.] | Desconhecida | por | 1889 | 1990 | 1880 | 1990 | 101 |
2597 | Documentos | Acta dos festejos civicos com que o povo de So... | Sobral, CE | 1822-1922 | NaN | NaN | não definido | 1822 | 1922 | 1820 | 1920 | 100 |
2551 | Diario Official [do] Imperio do Brasil | NaN | Rio de Janeiro, RJ | 1862-1959 | Imprensa Oficial | NaN | por | 1862 | 1959 | 1860 | 1950 | 97 |
2827 | Estrella do Minho | folha noticiosa, litteraria e bibliographica | Vila Nova de Famalicão [Portugal] | 1893-1987 | NaN | Semanal | por | 1893 | 1987 | 1890 | 1980 | 94 |
4516 | O Beijo | litterário crítico e artistico | Manaus, AM | 1897-1988 | Typ. do Amazonas Commercial | Indeterminada | não definido | 1897 | 1988 | 1890 | 1980 | 91 |
5345 | O Juvenil | NaN | Bom Sucesso, MG | 1892-1979 | NaN | Semanal | não definido | 1892 | 1979 | 1890 | 1970 | 87 |
1866 | Casamentos Alemães | NaN | Blumenau, SC | 1900-1985 | NaN | Indeterminada | por | 1900 | 1985 | 1900 | 1980 | 85 |
1192 | Alagoas Livre | NaN | Recife, PE | 1817-1901 | [s.n.] | Semanal | por | 1817 | 1901 | 1810 | 1900 | 84 |
3170 | Gazeta de Noticias | NaN | Rio de Janeiro, RJ | 1875-1956 | Typ. da Gazeta de Noticias | Diária | por | 1875 | 1956 | 1870 | 1950 | 81 |
3797 | Kolonie Zeitung | NaN | Joinville, SC | 1862-1942 | Typ. de C.W. Boehm | Indeterminada | por | 1862 | 1942 | 1860 | 1940 | 80 |
7535 | União Médica | archivo internacional de sciencias medicas | Rio de Janeiro, RJ | 1811-1890 | NaN | Desconhecida | por | 1811 | 1890 | 1810 | 1890 | 79 |
2985 | Folha do Norte | NaN | Belém, PA | 1896-1974 | Typ. da Folha do Norte | Diária | por | 1896 | 1974 | 1890 | 1970 | 78 |
Percebemos que os dois primeiro registros possuem contagem acima de 250 anos, o que representa um erro no dataframe. Na análise a seguir, vamos levar em conta apenas registros com no máximo 500 anos de publicação.
Vamos visualizar os periódicos com mais de 50 anos de publicação presentes no acervo:
# a coluna diff deve ter entre 50 e 200 anos
df_diff = df[(df['diff'] > 50) & (df['diff'] < 500)]
# organizar por diferença
df_diff = df_diff.sort_values(by='diff', ascending=False)
# excluir linhas com títulos, locais e anos de início iguais
df_diff = df_diff.drop_duplicates(subset=['title', 'place', 'start_year'], keep='first')
# criar gráfico
fig8 = bar_chart(df_diff, 'title', 'diff', 'Periódicos com maiores diferenças entre início e fim da publicação', range_x=None, range_y=None, color=None)
# adcionar texto nas barras
fig8.update_traces(texttemplate='%{y}', textposition='inside')
fig8.show()
# contar 'place' iguais no df_diff com mais de 10 anos de diferença
df_diff[df_diff['diff'] > 2]['place'].value_counts()
Rio de Janeiro, RJ 21
Recife, PE 3
Juiz de Fora, MG 2
São Paulo, SP 2
Blumenau, SC 2
Manaus, AM 2
Curitiba, PR 1
Porto Alegre, RS 1
Olinda, PE 1
Rio Grande, RS 1
Laguna, SC 1
Brasília, DF 1
Paraná 1
Lages, SC 1
São Leopoldo, RS 1
Desterro [Florianópolis, SC] 1
São Paulo 1
São Luis, MA 1
Santa Catarina 1
Pará, PA 1
Leopoldina, MG 1
Goiás, GO 1
Uberaba, MG 1
Garibaldi, RS 1
Canoinhas, SC 1
Belém, PA 1
Joinville, SC 1
Bom Sucesso, MG 1
Vila Nova de Famalicão [Portugal] 1
Sobral, CE 1
Aracaju, SE 1
Lisboa [Portugal] 1
Bom Despacho, MG 1
Name: place, dtype: int64
# criar gráfico com locais mais de 10 anos de diferença
df_diff_place = df_diff[df_diff['diff'] > 10]['place'].value_counts().rename_axis('Local').reset_index(name='quantidade')
# organizar por quantidade
df_diff_place = df_diff_place.sort_values(by='quantidade', ascending=False)
# criar gráfico
fig9 = bar_chart(df_diff_place, 'Local', 'quantidade', 'Locais com maior número de publicações com mais de 10 anos de diferença entre início e fim da publicação', range_x=None, range_y=None, color=None)
fig9.show()
Existem 21 periódicos com mais de 10 anos de publicação na cidade do Rio de Janeiro. Em seguida, temos Recife, com 3 periódicos, seguido de São Paulo, Juiz de Fora, Blumenau e Manaus, com 2 periódicos cada. Temos 27 cidades com 1 periódico cada na sequência.
Periodicidade#
# contar periodicidade
df['periodicity'].value_counts()
Desconhecida 2085
Semanal 1505
Mensal 425
Indeterminada 354
Quinzenal 308
Diária 258
2 vezes por semana 257
Anual 170
Irregular 94
2 vezes por mês 72
Bissemanal 61
3 vezes por semana 59
3 vezes por mês 31
Número único 29
Duas vezes por semana 28
Trimestral 28
Bimensal 26
Bimestral 17
4 vezes por mes 8
semanal: nos domingos 8
Varia 8
Bi-mensal 7
Trimensal 7
Semisemanal 5
Semestral 5
Três vezes por semana 4
6 vezes por mês 3
sábados 3
N. especial 3
semanal: domingo 2
semanal: no sábados 2
3 vezes ao mes 2
semanal: quarta-feira 2
Edição única 2
terça e sexta-feira 2
Mensal? 2
Quinzenal [1ª fase] 2
Duas vezes na semana 1
4 vezes por semana 1
Trimestral.(1ª e 2ª Fases) 1
Semanal, as quintas 1
Semanal: sabado 1
u 1
Quadrimestral 1
6 vezes por semana 1
Bissemestral 1
5 vezes por semana 1
quarta-feira e sábado 1
Sabado 1
semanal: todo sábado 1
Mensal (Edicao especial) 1
2 veses por mês 1
Regular 1
Trissemanal 1
Name: periodicity, dtype: int64
É possível perceber que os dados referentes à periodicidade dos periódicos também não estão padronizados. Vamos minimizar as diferenças entre as formas de registro dos dados para facilitar a análise.
# padronizar valores na coluna 'periodicity'
# substituir 2 por Duas
df['periodicity'] = df['periodicity'].replace(to_replace=r'2', value='Duas', regex=True)
# substituir 3 por Três
df['periodicity'] = df['periodicity'].replace(to_replace=r'3', value='Três', regex=True)
# substituir 4 por Quatro
df['periodicity'] = df['periodicity'].replace(to_replace=r'4', value='Quatro', regex=True)
# substituir ' mes' por ' mês'
df['periodicity'] = df['periodicity'].replace(to_replace=r' mes', value=' mês', regex=True)
# substituir Bi-mensal por Bimensal
df['periodicity'] = df['periodicity'].replace(to_replace=r'Bi-mensal', value='Bimensal', regex=True)
# substituir ' veses' por ' vezes'
df['periodicity'] = df['periodicity'].replace(to_replace=r' veses', value=' vezes', regex=True)
# colocar todos os valores em minúsculo
df['periodicity'] = df['periodicity'].str.lower()
Agora, vejamos a porcentagem de registros com periodicidade definida:
# contar porcentagem de periodicidade
df['periodicity'].value_counts(normalize=True)
desconhecida 0.353330
semanal 0.255042
mensal 0.072022
indeterminada 0.059990
quinzenal 0.052195
duas vezes por semana 0.048297
diária 0.043721
anual 0.028809
irregular 0.015930
duas vezes por mês 0.012371
três vezes por semana 0.010676
bissemanal 0.010337
bimensal 0.005592
três vezes por mês 0.005253
número único 0.004914
trimestral 0.004745
bimestral 0.002881
varia 0.001356
semanal: nos domingos 0.001356
quatro vezes por mês 0.001356
trimensal 0.001186
semisemanal 0.000847
semestral 0.000847
6 vezes por mês 0.000508
n. especial 0.000508
sábados 0.000508
edição única 0.000339
semanal: domingo 0.000339
mensal? 0.000339
semanal: no sábados 0.000339
quinzenal [1ª fase] 0.000339
terça e sexta-feira 0.000339
semanal: quarta-feira 0.000339
três vezes ao mês 0.000339
semanal, as quintas 0.000169
u 0.000169
trimestral.(1ª e duasª fases) 0.000169
quadrimestral 0.000169
duas vezes na semana 0.000169
quatro vezes por semana 0.000169
semanal: sabado 0.000169
quarta-feira e sábado 0.000169
bissemestral 0.000169
5 vezes por semana 0.000169
6 vezes por semana 0.000169
sabado 0.000169
semanal: todo sábado 0.000169
mensal (edicao especial) 0.000169
regular 0.000169
trissemanal 0.000169
Name: periodicity, dtype: float64
E visualizar os dados com um gráfico de pizza:
# Criar dataframe com valores de periodicidade maiores que 1%
df_periodicity = df['periodicity'].value_counts(normalize=True)
df_periodicity = df_periodicity[df_periodicity > 0.01]
# gráfico de pizza
fig10 = px.pie(df_periodicity, values='periodicity', names=df_periodicity.index, title='Porcentagem de periodicidade')
fig10.show()
Se excluirmos os registros sem periodicidade conhecida (que correspondem a 36,7%), percebemos que parte significativa do acervo, 41.9%, é composto por periódicos semanais. Em seguida, representando 11.8% do acervo temos periódicos mensais. Periódicos diários correspondem a apenas 7.17% do acervo.
Caso consideremos todo o acervo, incluindo periódicos com periodicidade desconhecida, as publicações semanais correspondem a 26.5%, mensais a 7.48% e diárias a 4.54%.
Locais de publicação#
# contar locais de publicação
df['place'].value_counts()
Rio de Janeiro, RJ 2185
São Paulo, SP 294
Florianópolis, SC 239
Recife, PE 207
Bahia [Salvador, BA] 192
...
Lageado, MT 1
Joinvelle 1
Tiradentes, MG 1
Duque de Caxias, RJ 1
Urussanga 1
Name: place, Length: 672, dtype: int64
Vamos contar quantos registros não possuem local de publicação definido e em seguida, incluir o valor ‘indeterminado’ para esses registros:
# contar place is null
df[df['place'].isnull()].count()
title 77
subtitle 39
place 0
period 42
publisher 20
periodicity 50
language 77
start_year 77
end_year 77
start_decade 77
end_decade 77
diff 77
dtype: int64
# adicionar 'indeterminado' nos locais nulos
df['place'] = df['place'].fillna('indeterminado')
Vamos criar um dataframe com os dados de cidades
# criar df com locais
df_place = df['place'].value_counts()
df_place = df_place.rename_axis('Cidades').reset_index(name='Quantidade')
# colocar Local em minúsculo
df_place['Cidades'] = df_place['Cidades'].str.lower()
# substituir [s.l.] por indeterminado
df_place['Cidades'] = df_place['Cidades'].replace(to_replace=r'\[s.l.\]', value='indeterminado', regex=True)
df_place
Cidades | Quantidade | |
---|---|---|
0 | rio de janeiro, rj | 2185 |
1 | são paulo, sp | 294 |
2 | florianópolis, sc | 239 |
3 | recife, pe | 207 |
4 | bahia [salvador, ba] | 192 |
... | ... | ... |
668 | santa cruz do sul ,rs | 1 |
669 | demétrio ribeiro [joão neiva, es] | 1 |
670 | jaguarana | 1 |
671 | águas de sao pedro, sp | 1 |
672 | urussanga | 1 |
673 rows × 2 columns
# criar gráfico de barras com os 20 locais com mais registros
fig11 = bar_chart(df_place.head(20), 'Cidades', 'Quantidade', '20 Cidades com mais registros', range_x=None, range_y=None, color=None)
# adcionar texto nas barras
fig11.update_traces(texttemplate='%{y}', textposition='inside')
fig11.show()
Vamos transformar esses dados em porcentagem e considerar apenas cidades com mais de 1% do total de registros:
#Criar gráfico de pizza com a porcentagem de periodicidade acima de 0.01
df_place = df['place'].value_counts(normalize=True)
df_place = df_place[df_place > 0.01]
df_place = df_place.rename_axis('Cidades').reset_index(name='Porcentagem')
# transformar porcentagem em número
df_place['Porcentagem'] = df_place['Porcentagem'] * 100
# mostrar apenas 3 casas decimais
df_place['Porcentagem'] = df_place['Porcentagem'].round(2)
df_place
Cidades | Porcentagem | |
---|---|---|
0 | Rio de Janeiro, RJ | 28.43 |
1 | São Paulo, SP | 3.83 |
2 | Florianópolis, SC | 3.11 |
3 | Recife, PE | 2.69 |
4 | Bahia [Salvador, BA] | 2.50 |
5 | Maceió, AL | 2.41 |
6 | Curitiba, PR | 1.85 |
7 | Manaus, AM | 1.69 |
8 | [S.l.] | 1.68 |
9 | Aracaju, SE | 1.55 |
10 | São Luis, MA | 1.46 |
11 | Desterro [Florianópolis, SC] | 1.35 |
12 | Porto Alegre, RS | 1.35 |
13 | Fortaleza, CE | 1.24 |
14 | Belém, PA | 1.17 |
15 | Fortaleza | 1.07 |
16 | Ouro Preto, MG | 1.00 |
17 | indeterminado | 1.00 |
18 | Pernambuco | 1.00 |
# gráfico de pizza
fig12 = px.pie(df_place, values='Porcentagem', names=df_place['Cidades'], title='Cidades com mais de 1% dos registros')
# valor absoluto no gráfico de pizza ao invés de porcentagem e acrescentar o caractere %
fig12.update_traces(textinfo='value', textfont_size=12, texttemplate='%{value:.2f}%')
fig12.show()
A cidade do Rio de Janeiro corresponde a 28,43% do total e 47,1% entre as cidades com pelo menos 1%. A cidade de São Paulo vem em seguida, mas com apenas 3,82% do total e 6,6% entre as cidades com pelo menos 1%. A diferença entre São Paulo e as seguintes é pequena: Florianópolis com 3,1%; Recife com 2,69%; Salvador com 2,49% e Maceió com 2,40%
# criar coluna com estado, pegando apenas o padrão ', dd' na coluna 'Local'
df['Estado'] = df['place'].str.extract(r',\s(\w\w)')
# remover ', ' da coluna 'Estado'
df['Estado'] = df['Estado'].str.replace(', ', '')
#colocar estado em maiúsculo
df['Estado'] = df['Estado'].str.upper()
df.head()
title | subtitle | place | period | publisher | periodicity | language | start_year | end_year | start_decade | end_decade | diff | Estado | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | O Abolicionista Paraense | NaN | Belém, PA | 1883- | Typ. da Provincia do Para | semanal | por | 1883 | 1883 | 1880 | 1880 | 0 | PA |
1 | O Abolicionista | propriedade de uma associação | São Luis, MA | 1885 | Typ. do Abolicionista | NaN | por | 1885 | 1885 | 1880 | 1880 | 0 | MA |
2 | O Academico | periodico scientifico, litterario e especialme... | Rio de Janeiro, RJ | 1855- | Typ. Fluminense, de D.L. dos Santos | NaN | por | 1855 | 1855 | 1850 | 1850 | 0 | RJ |
3 | A Actualidade | orgao do Partido Liberal | Ouro Preto, MG | 1878-1882 | Typ. de Jose Egydio da Silca Campos | três vezes por semana | não definido | 1878 | 1882 | 1870 | 1880 | 4 | MG |
4 | A Actualidade | periodico imparcial, litterario, critico e not... | Maranhão | 1900- | Typ. de Antonio Pereira Ramos d'Almeida e C. S... | três vezes por mês | por | 1900 | 1900 | 1900 | 1900 | 0 | NaN |
# agrupar por estado e contar valores únicos da coluna 'place'
df_state = df.groupby('Estado')['place'].nunique().rename_axis('Estado').reset_index(name='Quantidade')
# ordenar por quantidade
df_state = df_state.sort_values(by='Quantidade', ascending=False)
df_state
Estado | Quantidade | |
---|---|---|
12 | MG | 190 |
28 | SP | 59 |
26 | SC | 49 |
21 | RJ | 48 |
25 | RS | 27 |
4 | BA | 20 |
7 | ES | 20 |
5 | CE | 18 |
1 | AL | 16 |
15 | PA | 13 |
20 | PR | 12 |
2 | AM | 11 |
27 | SE | 11 |
18 | PI | 9 |
17 | PE | 7 |
0 | AC | 6 |
13 | MS | 6 |
11 | MA | 6 |
16 | PB | 4 |
14 | MT | 4 |
10 | GO | 4 |
22 | RN | 3 |
19 | PO | 2 |
24 | RR | 2 |
6 | DF | 2 |
29 | TO | 2 |
23 | RO | 1 |
9 | FR | 1 |
8 | EU | 1 |
3 | AP | 1 |
Apesar da centralidade da cidade do Rio de Janeiro nos números absolutos do acervo, é interessante notar que o estado do Rio de Janeiro possui apenas 48 cidades entre as localidades dos periódicos, atrás de Santa Catarina (49), São Paulo (59) e Minas Gerais, que apresenta o maior número de cidades no dataframe, com 190.
# gráfico de barras com a quantidade de registros por estado
fig13 = bar_chart(df_state, 'Estado', 'Quantidade', 'Quantidade de cidades por estado', range_x=None, range_y=None, color=None)
# adicionar texto nas barras
fig13.update_traces(texttemplate='%{y}', textposition='inside')
fig13.show()
Editoras#
# colocar editor em minúsculo
df['publisher'] = df['publisher'].str.lower()
# substituir Typografia e Tipografia por Typ.
df['publisher'] = df['publisher'].replace(to_replace=r'typografia', value='typ.', regex=True)
# substituir [s.n], s.n], [s.n por Não identificado
df['publisher'] = df['publisher'].replace(to_replace=r'\[s.n\]', value='não identificado', regex=True)
df['publisher'] = df['publisher'].replace(to_replace=r's.n.\]', value='não identificado', regex=True)
df['publisher'] = df['publisher'].replace(to_replace=r'\[s.n.', value='não identificado', regex=True)
df['publisher'] = df['publisher'].replace(to_replace=r's.n.', value='não identificado', regex=True)
df['publisher'] = df['publisher'].replace(to_replace=r'\[não identificado', value='não identificado', regex=True)
# contar editor
df['publisher'].value_counts()
não identificado 1800
typ. do diário 45
typ. nacional 43
typ. americana 33
typ. cosmopolita 32
...
typ. do brasil 1
diário de pernambuco 1
typ. de j.a. dos não identificadoos cardoso e irmao 1
typ. commercial, de a.j. da costa 1
typ. l. faria & cia. 1
Name: publisher, Length: 2014, dtype: int64
# criar df com editor
df_editor = df['publisher'].value_counts().rename_axis('Editor/a').reset_index(name='Quantidade')
df_editor
Editor/a | Quantidade | |
---|---|---|
0 | não identificado | 1800 |
1 | typ. do diário | 45 |
2 | typ. nacional | 43 |
3 | typ. americana | 33 |
4 | typ. cosmopolita | 32 |
... | ... | ... |
2009 | typ. do brasil | 1 |
2010 | diário de pernambuco | 1 |
2011 | typ. de j.a. dos não identificadoos cardoso e ... | 1 |
2012 | typ. commercial, de a.j. da costa | 1 |
2013 | typ. l. faria & cia. | 1 |
2014 rows × 2 columns
# gráfico de barras com os 20 editores com mais registros
fig14 = bar_chart(df_editor.head(20), 'Editor/a', 'Quantidade', '20 Editores com mais registros', range_x=None, range_y=None, color=None)
# adicionar texto nas barras
fig14.update_traces(texttemplate='%{y}', textposition='inside')
fig14.show()
# criar o mesmo gráfico mas sem o editor 'Não identificado'
fig15 = bar_chart(df_editor[1:21], 'Editor/a', 'Quantidade', '20 Editores com mais registros', range_x=None, range_y=None, color=None)
# adicionar texto nas barras
fig15.update_traces(texttemplate='%{y}', textposition='inside')
fig15.show()
# avaliar principais editores por estado
df_state_editor = df.groupby(['Estado', 'publisher'])['place'].nunique().rename_axis(['Estado', 'Editor/a']).reset_index(name='Quantidade')
# remover editor 'Não identificado'
df_state_editor = df_state_editor[df_state_editor['Editor/a'] != 'não identificado']
df_state_editor
Estado | Editor/a | Quantidade | |
---|---|---|---|
1 | AC | offic. d'o municipio | 1 |
2 | AC | prefeitura do alto purus, 1908- | 1 |
3 | AC | typ. da folha do acre | 1 |
4 | AC | typ. imprensa oficial do estado do acre | 1 |
5 | AC | typ. la paz | 1 |
... | ... | ... | ... |
2076 | SP | typ. união | 1 |
2077 | SP | typ. vanordem e cia | 1 |
2078 | SP | typ. vanorden e cia | 1 |
2079 | SP | typo-lithographia ribeiro | 1 |
2080 | SP | typographia brasil de carlos gerke | 1 |
2058 rows × 3 columns
# contar editor por estado
df_state_editor = df_state_editor.groupby('Estado')['Editor/a'].nunique().rename_axis('Estado').reset_index(name='Quantidade')
df_state_editor = df_state_editor.sort_values(by='Quantidade', ascending=False)
df_state_editor
Estado | Quantidade | |
---|---|---|
19 | RJ | 755 |
25 | SP | 185 |
10 | MG | 176 |
4 | BA | 132 |
23 | SC | 101 |
1 | AL | 97 |
15 | PE | 80 |
22 | RS | 77 |
13 | PA | 72 |
9 | MA | 64 |
18 | PR | 58 |
5 | CE | 58 |
24 | SE | 45 |
2 | AM | 39 |
7 | ES | 30 |
20 | RN | 26 |
16 | PI | 26 |
12 | MT | 19 |
0 | AC | 6 |
6 | DF | 4 |
8 | GO | 2 |
11 | MS | 2 |
21 | RO | 1 |
3 | AP | 1 |
14 | PB | 1 |
17 | PO | 1 |
Palavras mais frequentes nos títulos e subtítulos#
Vamos analisar as palavras mais frequentes nos títulos e subtítulos dos periódicos digitalizados (desde que tenham mais de 4 caracteres).
# criar dataframe com a quantidade de títulos
df_title = df['title'].str.lower().value_counts().rename_axis('Título').reset_index(name='Quantidade')
df_title
Título | Quantidade | |
---|---|---|
0 | o progresso | 37 |
1 | o municipio | 30 |
2 | o democrata | 25 |
3 | o imparcial | 22 |
4 | o commercio | 21 |
... | ... | ... |
5365 | ensaio litterario | 1 |
5366 | ensaio juridico e litterario | 1 |
5367 | ensaio escolatico dos estudantes do atheneo tu... | 1 |
5368 | semanario do cincinnato | 1 |
5369 | o zig-zag | 1 |
5370 rows × 2 columns
# listar os 20 títulos com mais registros
df_title.head(20).style.hide(axis="index")
Título | Quantidade |
---|---|
o progresso | 37 |
o municipio | 30 |
o democrata | 25 |
o imparcial | 22 |
o commercio | 21 |
o liberal | 20 |
jornal do commercio | 19 |
o povo | 18 |
o popular | 18 |
a ordem | 18 |
o constitucional | 18 |
o trabalho | 18 |
o conservador | 17 |
o tempo | 16 |
relatorios dos presidentes dos estados brasileiros : primeira republica | 16 |
a noticia | 16 |
a verdade | 15 |
a semana | 14 |
a luz | 14 |
jornal do povo | 13 |
# ler a coluna título e, df_title e contar palavras únicas e a quantidade de vezes que aparecem
# mostrar apenas palavras mais longas que 3 caracteres
df_title_words = df['title'].str.lower().str.split(expand=True).stack().value_counts().rename_axis('Palavra').reset_index(name='Quantidade')
df_title_words = df_title_words[df_title_words['Palavra'].str.len() > 3]
df_title_words.head(50).style.hide(axis="index")
Palavra | Quantidade |
---|---|
jornal | 396 |
revista | 310 |
gazeta | 220 |
correio | 212 |
folha | 151 |
diario | 147 |
povo | 147 |
litterario | 138 |
orgao | 104 |
echo | 98 |
commercio | 97 |
periodico | 96 |
commercial | 90 |
tribuna | 87 |
estado | 85 |
noticioso | 82 |
liberal | 81 |
almanak | 69 |
brazil | 67 |
brasil | 64 |
para | 64 |
popular | 62 |
progresso | 62 |
orgam | 60 |
almanach | 60 |
norte | 57 |
municipio | 56 |
provincia | 54 |
janeiro | 52 |
republica | 51 |
boletim | 51 |
constitucional | 51 |
mercantil | 50 |
conservador | 50 |
cidade | 49 |
nova | 49 |
nacional | 48 |
tarde | 48 |
minas | 47 |
interesses | 47 |
fluminense | 45 |
semana | 44 |
litteraria | 43 |
imparcial | 43 |
liberdade | 43 |
partido | 43 |
recreativo | 42 |
verdade | 42 |
official | 42 |
critico | 41 |
# gráfico de barras com as 50 palavras mais frequentes
fig16 = bar_chart(df_title_words.head(50), 'Palavra', 'Quantidade', 'Títulos - 50 palavras mais frequentes', range_x=None, range_y=None, color=None)
# adicionar texto nas barras
fig16.update_traces(texttemplate='%{y}', textposition='inside')
fig16.show()
# criar dataframe com a quantidade de subtítulos
df_subtitle = df['subtitle'].str.lower().value_counts().rename_axis('Subtítulo').reset_index(name='Quantidade')
df_subtitle
Subtítulo | Quantidade | |
---|---|---|
0 | orgam republicano | 22 |
1 | orgam imparcial | 17 |
2 | periodico litterario e recreativo | 16 |
3 | periodico litterario e noticioso | 14 |
4 | orgam do partido republicano | 14 |
... | ... | ... |
2744 | revista dos interesses publicos | 1 |
2745 | orgam do gremio i e b dos empregados no commercio | 1 |
2746 | periodico semanal, literario e recreativo | 1 |
2747 | jornal redigido por academicos | 1 |
2748 | periodico encyclopedico | 1 |
2749 rows × 2 columns
# listar os 20 subtítulos com mais registros
df_subtitle.head(20).style.hide(axis="index")
Subtítulo | Quantidade |
---|---|
orgam republicano | 22 |
orgam imparcial | 17 |
periodico litterario e recreativo | 16 |
periodico litterario e noticioso | 14 |
orgam do partido republicano | 14 |
periodico critico e litterario | 13 |
periodico scientifico e litterario | 13 |
semanario independente | 13 |
orgao do partido conservador | 12 |
jornal politico | 12 |
jornal politico e noticioso | 12 |
orgao imparcial | 12 |
folha popular | 10 |
jornal independente | 10 |
orgao do partido republicano | 10 |
orgam independente e noticioso | 9 |
jornal politico, litterario e commercial | 9 |
jornal litterario | 8 |
orgam independente | 8 |
periodico critico e chistoso | 8 |
# ler a coluna subtítulo em df_subtitle e contar palavras únicas e a quantidade de vezes que aparecem
# mostrar apenas palavras mais longas que 3 caracteres
df_subtitle_words = df['subtitle'].str.lower().str.split(expand=True).stack().value_counts().rename_axis('Palavra').reset_index(name='Quantidade')
df_subtitle_words = df_subtitle_words[df_subtitle_words['Palavra'].str.len() > 3]
df_subtitle_words.head(50).style.hide(axis="index")
Palavra | Quantidade |
---|---|
jornal | 609 |
noticioso | 576 |
litterario | 524 |
orgam | 502 |
orgao | 483 |
periodico | 481 |
orgão | 309 |
interesses | 246 |
critico | 220 |
folha | 183 |
revista | 178 |
commercial | 176 |
semanario | 174 |
litterario, | 173 |
partido | 167 |
republicano | 159 |
politico | 143 |
politico, | 139 |
dedicado | 128 |
recreativo | 118 |
independente | 112 |
critico, | 98 |
humoristico | 97 |
litteraria | 93 |
imparcial | 79 |
noticioso, | 75 |
mensal | 63 |
commercial, | 61 |
municipio | 60 |
commercio | 59 |
scientifico | 58 |
sociedade | 56 |
propaganda | 56 |
povo | 54 |
para | 52 |
noticiosa | 51 |
club | 51 |
semanal | 51 |
conservador | 50 |
hebdomadario | 50 |
literario | 49 |
liberal | 48 |
popular | 46 |
artes | 44 |
industria | 43 |
illustrado | 39 |
official | 38 |
politica, | 38 |
estado | 35 |
lavoura | 35 |
# gráfico de barras com as 50 palavras mais frequentes
fig17 = bar_chart(df_subtitle_words.head(50), 'Palavra', 'Quantidade', 'Subtítulos - 50 palavras mais frequentes', range_x=None, range_y=None, color=None)
# adicionar texto nas barras
fig17.update_traces(texttemplate='%{y}', textposition='inside')
fig17.show()
Dataframe final#
Vamos criar um dataframe com as novas colunas e dados limpos criados ao longo desse notebook:
# save df to csv
df.to_csv('../../../data/dataframe_hdb.csv', index=False)
Considerações finais#
Os dados da HDB abrem possibilidades de análise aprofundada de seu acervo, limitações e vieses, assim como permite um estudo da própria história da imprensa no Brasil. De maneira geral, percebemos que o acervo apresenta uma centralidade para periódicos publicados na cidade do Rio de Janeiro, entre os anos 1860 e 1920; periódicos majoritariamente publicados em língua portuguesa; com periodicidade variada, mas com destaque para periódicos semanais e mensais. Também podemos perceber que a vida da maioria dos periódicos foi bastante efêmera, com 5694 periódicos tendo apenas um ano de publicação registrado no acervo de um total de 7685. Isso corresponde a 74,1% dos periódicos. Apenas 1991 periódicos possuem mais de um ano de publicação registrado no acervo, o que corresponde a 25,9% do total.
Muitas reflexões históricas importantes podem ser feitas a partir desses dados, assim como comparações com o acervo da Biblioteca Nacional Digital de Portugal.