<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hilton Fernandes</title>
    <description>The latest articles on DEV Community by Hilton Fernandes (@hilton_fernandes_eaac26ab).</description>
    <link>https://dev.to/hilton_fernandes_eaac26ab</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3451189%2F8daac153-76e1-4d43-b3cd-143771a97d38.jpg</url>
      <title>DEV Community: Hilton Fernandes</title>
      <link>https://dev.to/hilton_fernandes_eaac26ab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hilton_fernandes_eaac26ab"/>
    <language>en</language>
    <item>
      <title>Busca em arquivos binários</title>
      <dc:creator>Hilton Fernandes</dc:creator>
      <pubDate>Sat, 22 Aug 2026 18:04:59 +0000</pubDate>
      <link>https://dev.to/hilton_fernandes_eaac26ab/busca-em-arquivos-binarios-38k0</link>
      <guid>https://dev.to/hilton_fernandes_eaac26ab/busca-em-arquivos-binarios-38k0</guid>
      <description>&lt;p&gt;Algumas vezes é necessário fazer buscas em arquivos binários. Há relativamente poucos tutoriais disponíveis na Web sobre o tema, apesar das ferramentas disponíveis no Linux oferecerem recursos para isso.&lt;/p&gt;

&lt;p&gt;Este tutorial é escrito para apresentar esses recursos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visualização do arquivo com &lt;code&gt;hexdump&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;O programa &lt;code&gt;hexdump&lt;/code&gt; não está disponível nas instalações padrão do Linux. &lt;/p&gt;

&lt;p&gt;Assim, é preciso instalalá-lo. Em distribuições derivadas do Debian (como Ubuntu, Linux Mint etc.), isto pode ser feito com o familiar comando&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;hexdump
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A partir daí, uma apresentação muito conveniente é dada pela opção &lt;code&gt;-C&lt;/code&gt;, que mostrará o conteúdo do arquivo em hexadecimal e ao lado, uma tentativade mostrá-lo em ASCII.&lt;/p&gt;

&lt;p&gt;Vamos usar, nos exemplos a seguir, o conto &lt;em&gt;Quem boa cama faz&lt;/em&gt;* de Machado de Assis, que é um pequeno arquivo PDF disponível para ser baixado legal e gratuitamente em&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dominiopublico.mec.gov.br/download/texto/ua000225.pdf" rel="noopener noreferrer"&gt;https://dominiopublico.mec.gov.br/download/texto/ua000225.pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É um texto breve, de 19 páginas, com tamanho de apenas 64 kb.&lt;/p&gt;

&lt;p&gt;Segue a apresentação das primeiras 10 linhas, obtidas com os comandos&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hexdump -C ua000225.pdf | head&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Neste caso o programa &lt;code&gt;head&lt;/code&gt; mostra as 10 primeiras linhas da saída da execução de &lt;code&gt;hexdump -C&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A barra em pé &lt;code&gt;|&lt;/code&gt; chamada de &lt;em&gt;pipe&lt;/em&gt; ou "canalização", conecta a saída de &lt;code&gt;hexdump -C&lt;/code&gt; com a entrada de &lt;code&gt;head&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;00000000  25 50 44 46 2d 31 2e 32  20 0d 0a 25 e2 e3 cf d3  |%PDF-1.2 ..%....|
00000010  0d 0a 20 0d 0a 38 20 30  20 6f 62 6a 0d 0a 3c 3c  |.. ..8 0 obj..&amp;lt;&amp;lt;|
00000020  0d 0a 2f 4c 65 6e 67 74  68 20 39 20 30 20 52 0d  |../Length 9 0 R.|
00000030  0a 2f 46 69 6c 74 65 72  20 2f 46 6c 61 74 65 44  |./Filter /FlateD|
00000040  65 63 6f 64 65 20 0d 0a  3e 3e 0d 0a 73 74 72 65  |ecode ..&amp;gt;&amp;gt;..stre|
00000050  61 6d 0d 0a 48 89 85 96  &lt;span class="nb"&gt;dd &lt;/span&gt;6e 62 39 0c c7 9f 80  |am..H....nb9....|
00000060  77 c8 65 47 da 93 c6 76  3e 7b 35 14 a8 54 69 a7  |w.eG...v&amp;gt;&lt;span class="o"&gt;{&lt;/span&gt;5..Ti.|
00000070  d3 d1 d2 3b 6e ce 00 &lt;span class="nb"&gt;dd  &lt;/span&gt;65 05 54 0b 6a 2b f5 e9  |...&lt;span class="p"&gt;;&lt;/span&gt;n...e.T.j+..|
00000080  c7 49 ce a1 b4 98 1d 21  50 48 9c ff cf 71 e2 38  |.I.....!PH...q.8|
00000090  d7 d3 81 c5 a4 42 8c 1a  9d 52 d3 f1 c0 28 a3 9d  |.....B...R...&lt;span class="o"&gt;(&lt;/span&gt;..|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os arquivos PDF possuem muitas informações codificadas em binário, mas também têm conteúdo em texto ASCII. Por exemplo, neste caso, o arquivo contém o texto &lt;code&gt;/FlateDecode&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Outras informações podem ser obtidas paginando a execução de &lt;code&gt;hexdump -C&lt;/code&gt; por mais linhas, usando, por exemplo, &lt;code&gt;hexdump -C | less&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Busca com &lt;code&gt;grep&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Para buscar um padrão específico em um arquivo, o comando &lt;code&gt;grep&lt;/code&gt; é uma espécie canivete suíço -- com múltiplas utilidades.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkqbi1belifjq53h3pc3v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkqbi1belifjq53h3pc3v.jpg" alt=" " width="799" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Uma busca simples em um arquivo de textos comum -- por exemplo, o código fonte de um programa --, a sintaxe de &lt;code&gt;grep&lt;/code&gt; é trivial:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grep '&lt;/code&gt;&lt;em&gt;padrão&lt;/em&gt;&lt;code&gt;'&lt;/code&gt;&lt;em&gt;nome_do_arquivo&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Para buscas em arquivos binários, outras opções são necessárias. Segue uma lista delas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-a&lt;/code&gt; ou &lt;code&gt;--text&lt;/code&gt; faz com que &lt;code&gt;grep&lt;/code&gt; ignore marcações especiais no arquivo binário;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-b&lt;/code&gt; ou &lt;code&gt;--byte-offset&lt;/code&gt; faz com que &lt;code&gt;grep&lt;/code&gt; mostre o deslocamento (ou &lt;em&gt;offset&lt;/em&gt;) em &lt;em&gt;bytes&lt;/em&gt; da cadeia de caracteres encontrada.&lt;/p&gt;

&lt;p&gt;Neste caso, &lt;em&gt;offset&lt;/em&gt; significa que o primeiro byte é  referidocomo&lt;code&gt;0&lt;/code&gt;, o segundo como &lt;code&gt;1&lt;/code&gt; etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-o&lt;/code&gt; ou &lt;code&gt;--only-matching&lt;/code&gt; faz com que &lt;code&gt;grep&lt;/code&gt; mostre apenas a cadeia de caracteres que atende os critérios de busca.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para localizar a cadeia de caracteres &lt;code&gt;Filter&lt;/code&gt; no arquivo &lt;code&gt;ua000225.pdf&lt;/code&gt; aqui usado como exemplo, pode-se fazer&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'Filter'&lt;/span&gt; ua000225.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como sabemos que há muitas ocorrências da palavra &lt;code&gt;Filter&lt;/code&gt; neste pequeno arquivo, vamos restringir sua busca por apenas 1 ocorrência, usando novamente o utilitário &lt;code&gt;head&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'Filter'&lt;/span&gt; ua000225.pdf | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isto gerará a saída:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;50:Filter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isto significa que a palavra Filter começa a partir da posição 51 do&lt;br&gt;
arquivo &lt;code&gt;ua000225.pdf&lt;/code&gt; O que, segundo alguns, é uma boa ideia.&lt;/p&gt;
&lt;h3&gt;
  
  
  Expressões regulares
&lt;/h3&gt;

&lt;p&gt;Para aumentar ainda mais o poder do &lt;code&gt;grep&lt;/code&gt; há o recurso das&lt;br&gt;
&lt;a href="https://pt.wikipedia.org/wiki/Express%C3%A3o_regular" rel="noopener noreferrer"&gt;expressões regulares&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esse recurso é muito poderoso e pode até mesmo se tornar complexo. Aqui, usaremos apenas o mínimo delas.&lt;/p&gt;

&lt;p&gt;Para usar expressões regulares com o &lt;code&gt;grep&lt;/code&gt; pode-se usar a opção &lt;code&gt;-E&lt;/code&gt; ou &lt;code&gt;--extended-regexp&lt;/code&gt;, que permite certas simplificações.&lt;/p&gt;

&lt;p&gt;Por exemplo, para encontrar todas palavras iniciadas por uma letra maiúscula e seguidas por pelo menos uma letra minúscula, usa-se como expressão de busca o texto &lt;code&gt;[A-Z][a-z]\+&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As expressões &lt;code&gt;[A-Z]&lt;/code&gt; e &lt;code&gt;[a-z]&lt;/code&gt; indicam &lt;strong&gt;classes de caracteres&lt;/strong&gt;. No caso, respectivamente todas as letras maiúsculas e todas as letras minúsculas. O sinal &lt;code&gt;+&lt;/code&gt; indica que o caractere anterior deve aparecer pelo menos uma vez, sem limite de repetições.&lt;/p&gt;

&lt;p&gt;O caracter &lt;code&gt;+&lt;/code&gt; é prefixado por uma contrabarra, ou &lt;code&gt;\&lt;/code&gt; para distinguir essa repetição da busca do caracter &lt;code&gt;+&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Então, neste caso, o comando se torna:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'[A-Z][a-z]\+'&lt;/span&gt; ua000225.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Então, surgem 1088 linhas. Para restringir a busca a apenas 10 linhas, usamos novamente &lt;code&gt;head&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'[A-Z][a-z]\+'&lt;/span&gt; ua000225.pdf | &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que gera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;35:Length
50:Filter
58:Flate
63:Decode
109:Ti
160:Ae
279:Tc
283:Kpj
292:Hu
340:Rɢ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As cadeias de caracteres muito curtas (como &lt;code&gt;Ti&lt;/code&gt; ou &lt;code&gt;Ae&lt;/code&gt;) possivelmente são combinações aleatórias de valores binários. É possível exigir comprimentos mínimos maiores de resultados de busca. Uma das formas é usar as chaves.&lt;/p&gt;

&lt;p&gt;Uma curiosidade é que quando se usa &lt;code&gt;+&lt;/code&gt; em vez de &lt;code&gt;+&lt;/code&gt;, o resultado é&lt;br&gt;
diferente. Ou seja: os comandos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'[A-Z][a-z]+'&lt;/span&gt; ua000225.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;geram&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;12090:Yk+
24288:Ld+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A breve visualização do arquivo mostrou que as palavras maiores são&lt;br&gt;
precedidas por uma barra &lt;code&gt;/&lt;/code&gt;. Assim, pode-se alterar a expressão de busca para&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'/[A-Z][a-z]\+'&lt;/span&gt; ua000225.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isto gerará 428 ocorrências no arquivo em uso. Para restringi-las, usa-se&lt;br&gt;
novamente o &lt;code&gt;head&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'/[A-Z][a-z]\+'&lt;/span&gt; ua000225.pdf | &lt;span class="nb"&gt;head&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E finalmente,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;34:/Length
49:/Filter
57:/Flate
339:/Rɢ
992:/Type
1008:/Subtype
1017:/Image
1025:/Name
1037:/Filter
1058:/Width
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Separação de campos
&lt;/h3&gt;

&lt;p&gt;Para usar os resultados das buscas, pode-se aplicar o utilitário padrão &lt;code&gt;awk&lt;/code&gt;, que permite separar o &lt;em&gt;offset&lt;/em&gt; da cadeia de caracteres.&lt;/p&gt;

&lt;p&gt;Por exemplo, para extrair apenas a cadeia de caracteres:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'/[A-Z][a-z]\+'&lt;/span&gt; ua000225.pdf | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt; &lt;span class="s1"&gt;'{ print $2 }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para apresentar apenas as primeiras linhas, usa-se de novo &lt;code&gt;head&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'/[A-Z][a-z]\+'&lt;/span&gt; ua000225.pdf | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt; &lt;span class="s1"&gt;'{ print $2 }'&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que gera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/Length
/Filter
/Flate
/Rɢ
/Type
/Subtype
/Image
/Name
/Filter
/Width
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou para extrair apenas o &lt;em&gt;offset&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'/[A-Z][a-z]\+'&lt;/span&gt; ua000225.pdf | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt; &lt;span class="s1"&gt;'{ print $1 }'&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com o resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;34
49
57
992
1008
1017
1025
1037
1058
1070
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pelos exemplos, não é tão difícil ver que o comando &lt;code&gt;awk&lt;/code&gt; está permitindo separar os elementos da saída de &lt;code&gt;grep&lt;/code&gt;. A opção &lt;code&gt;-F ':'&lt;/code&gt;' define o caracter de separação entre os dois campos, que é &lt;code&gt;:'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A forma &lt;code&gt;$1&lt;/code&gt; define o primeiro campo (o &lt;em&gt;offset&lt;/em&gt;) e a forma &lt;code&gt;$2&lt;/code&gt; define o&lt;br&gt;
segundo campo, que é a cadeia de caracteres encontrada.&lt;/p&gt;
&lt;h3&gt;
  
  
  Contagem de ocorrências
&lt;/h3&gt;

&lt;p&gt;Para contar quantas vezes uma determinada string aparece, podem-se suar dois comandos, &lt;code&gt;sort&lt;/code&gt; e &lt;code&gt;uniq&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O comando &lt;code&gt;sort&lt;/code&gt; (literalmente "classificação") ordena a saída de &lt;code&gt;grep&lt;/code&gt;. Assim, a linha&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'/[A-Z][a-z]\+'&lt;/span&gt; ua000225.pdf | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt; &lt;span class="s1"&gt;'{ print $2 }'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vai mostrar&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/Amer
/Amer
/Arial
/Arial
/Arial
/Arial
/Ascent
/Ascent
/Ascent
/Ascent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que permite contar que &lt;code&gt;/Amer&lt;/code&gt; occore 2 vezes e &lt;code&gt;/Arial&lt;/code&gt; ocorre 4 vezes.&lt;/p&gt;

&lt;p&gt;Para contar todas as ocorrências, usa-se &lt;code&gt;uniq -c&lt;/code&gt;. Assim, a linha&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'/[A-Z][a-z]\+'&lt;/span&gt; ua000225.pdf | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt; &lt;span class="s1"&gt;'{ print $2 }'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;mostra&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;2 /Amer
4 /Arial
6 /Ascent
6 /Avg
6 /Base
2 /Batang
1 /Bi
1 /Bits
2 /Cal
6 /Cap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso não se queira a contagem, deixa-se de lado o &lt;code&gt;-c&lt;/code&gt; do &lt;code&gt;uniq&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Assim, a linha&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'/[A-Z][a-z]\+'&lt;/span&gt; ua000225.pdf | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt; &lt;span class="s1"&gt;'{ print $2 }'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;agora mostra&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/Amer
/Arial
/Ascent
/Avg
/Base
/Batang
/Bi
/Bits
/Cal
/Cap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por último, para se saber quais são as cadeias de caracteres mais comuns,faz-se&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'/[A-Z][a-z]\+'&lt;/span&gt; ua000225.pdf | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt; &lt;span class="s1"&gt;'{ print $2 }'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que gera&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;49 /Font
38 /Type
23 /Parent
21 /Length
21 /Filter
20 /Flate
19 /Resources
19 /Proc
19 /Page
19 /Contents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A opção &lt;code&gt;-r&lt;/code&gt; de &lt;code&gt;sort&lt;/code&gt; faz com que a ordenação seja decrescente: do mais frequente para o menos frequente. A opção &lt;code&gt;-n&lt;/code&gt; faz com que o primeiro campo da saída seja interpretado como um número.&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>regex</category>
      <category>tutorial</category>
      <category>howto</category>
    </item>
    <item>
      <title>Leveling with cluster analysis in Python: basic Python concepts</title>
      <dc:creator>Hilton Fernandes</dc:creator>
      <pubDate>Thu, 06 Nov 2025 21:36:06 +0000</pubDate>
      <link>https://dev.to/hilton_fernandes_eaac26ab/leveling-with-cluster-analysis-in-python-basic-python-concepts-1n6</link>
      <guid>https://dev.to/hilton_fernandes_eaac26ab/leveling-with-cluster-analysis-in-python-basic-python-concepts-1n6</guid>
      <description>&lt;p&gt;This is the 2nd of a series of 5 little articles that intend to present a simple idea of time series, and their implementation in Python. The purpose here is to present both a time series problem, and how we can solve it in simple Python code.&lt;/p&gt;

&lt;p&gt;Only very basic knowledge of Python and time series are needed as most concepts will be explained with care and references to longer tutorials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://dev.to/hilton_fernandes_eaac26ab/leveling-with-cluster-analysis-in-python-400p"&gt;1st article of the series&lt;/a&gt; presented the basic concepts of this series. This one, the 2nd one will present basic Python concepts and techniques to be used in the solution. The 3rd one will present a solution implemented in Python. The 4th article will add a sinusoidal decomposition of the data after the filtering of the solution. And the 5th and last one will use all the elements to address a real problem in cryptocurrencies.&lt;br&gt;
'&lt;/p&gt;
&lt;h2&gt;
  
  
  Some simple Python ideas
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Libraries, modules and submodules
&lt;/h3&gt;

&lt;p&gt;Isaac Newton, that created a huge part of modern Physics and Mathematics once said the &lt;a href="https://en.wikiquote.org/wiki/Isaac_Newton#Quotes" rel="noopener noreferrer"&gt;he could see further because because he standed in the shoulder of giants&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This concept is behind most software codes: they do not create everything, they use a large part of what was already created, mainly in the form of &lt;a href="https://en.wikipedia.org/wiki/Library_(computing)" rel="noopener noreferrer"&gt;sofware libraries&lt;/a&gt;. Python is very good at this, and here is the part of the code used here that will use some libraries. In Python, a library is usually named a &lt;em&gt;module&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sklearn.cluster&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;KMeans&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea that the current code will bring information from another one is encompassed in the word &lt;code&gt;import&lt;/code&gt; in the code above. Another important point is that programmers usually prefer to write less. So, in the 1st line, the library &lt;code&gt;numpy&lt;/code&gt; is renamed as &lt;code&gt;np&lt;/code&gt;. In another line, the module &lt;code&gt;matplotlib.pyplot&lt;/code&gt; is renamed simply as &lt;code&gt;plt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And in the last line of the code, another shortening is presented: instead of renaming a code fragment in a shorter from, Python lets one pick only what a programmer needs. In this case, only &lt;code&gt;KMeans&lt;/code&gt; will be picked from &lt;code&gt;sklearn.cluster&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A less important point is that use of a dot lets selecting a part of a module; that is: a &lt;em&gt;submodule&lt;/em&gt;. In the code shown, &lt;code&gt;matplotlib.pyplot&lt;/code&gt; means the submodule &lt;code&gt;pyplot&lt;/code&gt; of the module &lt;code&gt;matplotlib&lt;/code&gt;. And, of course, &lt;code&gt;sklearn.cluster&lt;/code&gt; is the submodule &lt;code&gt;cluster&lt;/code&gt; of the module &lt;code&gt;sklearn&lt;/code&gt;. Creating submodules increases the organization of larger modules, as this divides them in specialized parts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pieces of information in scalar variables
&lt;/h3&gt;

&lt;p&gt;The next part of the code deals with storing information that shall be processed. Here a list of &lt;em&gt;scalar variables&lt;/em&gt;, or variables that are individual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;coeff&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;

&lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
&lt;span class="n"&gt;ladder&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;
&lt;span class="n"&gt;n_points&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;
&lt;span class="n"&gt;n_half&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n_points&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n_points&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two types of information in this code fragment: &lt;code&gt;int&lt;/code&gt;, that hold only integral values. In this case the count of points (&lt;code&gt;n_point&lt;/code&gt;) and the half of that count, &lt;code&gt;n_half&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The double bar in the line for &lt;code&gt;n_half&lt;/code&gt; is used to make sure the division of &lt;code&gt;n_points&lt;/code&gt; by &lt;code&gt;2&lt;/code&gt; will generate a number of type &lt;code&gt;int&lt;/code&gt;, and not a &lt;code&gt;float&lt;/code&gt; number. That is: it will hold &lt;code&gt;50&lt;/code&gt;, and not &lt;code&gt;50.5&lt;/code&gt;, as the division of &lt;code&gt;101&lt;/code&gt; by &lt;code&gt;2&lt;/code&gt; would create.&lt;/p&gt;

&lt;p&gt;The type &lt;code&gt;float&lt;/code&gt; can be used to hold number with a decimal part. For instance, &lt;code&gt;coeff&lt;/code&gt; will be used to hold a coefficient. In this case, &lt;code&gt;0.25&lt;/code&gt;.  Since the problem here is to represent a discontuinuity, a set of values will be close to a &lt;code&gt;base&lt;/code&gt; level, while other ones will be above it, in &lt;code&gt;ladder&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And finally, &lt;code&gt;delta&lt;/code&gt; holds the step that will be used as a clock tick in our time series.&lt;/p&gt;

&lt;h3&gt;
  
  
  A data generator
&lt;/h3&gt;

&lt;p&gt;A time series usually is a series of data collected along the time. For instance, mean wage in a certain year. But to avoid the need of getting real data, this code will generate its own data. By means of a &lt;a href="https://en.wikipedia.org/wiki/Pseudorandom_number_generator" rel="noopener noreferrer"&gt;pseudorandom number generator&lt;/a&gt;, aka PRNG. In a few words, a PRNG is a mathematical algorithm that can generate a sequence of numbers without any pattern; that is: they look random. It's called &lt;em&gt;pseudorandom&lt;/em&gt; because if one such algorithm is fed with a constant &lt;em&gt;seed&lt;/em&gt; it will always generate the same sequence of numbers.&lt;/p&gt;

&lt;p&gt;In this case it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;rng&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_rng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, &lt;code&gt;rng&lt;/code&gt; is the name of the fabric of numbers, and it's created by calling the &lt;em&gt;function&lt;/em&gt; (or piece of code) &lt;code&gt;defaut_rng&lt;/code&gt; with the parameter &lt;code&gt;42&lt;/code&gt;.  This function is in the submodule &lt;code&gt;np.random&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pieces of information in arrays
&lt;/h3&gt;

&lt;p&gt;Since a time series contain several data, a &lt;em&gt;scalar variable&lt;/em&gt; can't be used to contain it. The module &lt;code&gt;numpy&lt;/code&gt; has the resource of &lt;em&gt;arrays&lt;/em&gt; or &lt;code&gt;ndarrays&lt;/code&gt;. In an array, the elements are identified by an &lt;em&gt;index&lt;/em&gt;, that is analogous to the apartment number in a building.&lt;/p&gt;

&lt;p&gt;The following code fragment creates the arrays needed to this problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;linspace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;n_points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n_half&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;ladder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the 1st line, the array &lt;code&gt;x&lt;/code&gt; receives &lt;code&gt;n_points&lt;/code&gt; (aka &lt;code&gt;101&lt;/code&gt;) numbers from &lt;code&gt;0.0&lt;/code&gt; to &lt;code&gt;1.0&lt;/code&gt;, subdivided in increments of &lt;code&gt;0.01&lt;/code&gt;; that is: &lt;code&gt;0.0&lt;/code&gt;, &lt;code&gt;0.01&lt;/code&gt;, &lt;code&gt;0.02&lt;/code&gt;, ..., &lt;code&gt;0.99&lt;/code&gt;, &lt;code&gt;1.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the 2nd line, the array &lt;code&gt;y&lt;/code&gt; receives &lt;code&gt;n_points&lt;/code&gt; numbers chosen &lt;em&gt;pseudorandomly&lt;/em&gt; between &lt;code&gt;-05&lt;/code&gt; and &lt;code&gt;0.5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the third line, the 2nd half of &lt;code&gt;y&lt;/code&gt; receives an increment of &lt;code&gt;ladder&lt;/code&gt;. That creates  the discontinuity to be solved in the remaining of the texts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plotting the data
&lt;/h2&gt;

&lt;p&gt;Please consider the following code fragment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;fig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subplots&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;y&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visible&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 1st line is a generic one, that can be used to create &lt;em&gt;plots&lt;/em&gt; -- aka charts -- much more complicated than the ones used here. For instance, several plots in the same image.&lt;/p&gt;

&lt;p&gt;The 2nd line plots the elements of two arrays, taking care of connecting by lines each one of their values.&lt;/p&gt;

&lt;p&gt;The 3rd and 4th lines of the code label the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; axis.&lt;/p&gt;

&lt;p&gt;The 5th line of the code create a grid to ease the visualization of data. And the 6th and final line causes the chart to be shown in the screen.&lt;/p&gt;

&lt;p&gt;The final result is like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1hv5vkfi32omlyezfty.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1hv5vkfi32omlyezfty.jpeg" alt="A time series with a discontinuity" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>python</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Leveling with cluster analysis in Python: general concepts</title>
      <dc:creator>Hilton Fernandes</dc:creator>
      <pubDate>Thu, 30 Oct 2025 18:52:11 +0000</pubDate>
      <link>https://dev.to/hilton_fernandes_eaac26ab/leveling-with-cluster-analysis-in-python-400p</link>
      <guid>https://dev.to/hilton_fernandes_eaac26ab/leveling-with-cluster-analysis-in-python-400p</guid>
      <description>&lt;p&gt;Financial markets have discontinuities: sometimes a price jumps up or down in a time so short that it can be considered a real discontinuity if the time measured by our clocks were really continuous, real-line continuous.&lt;/p&gt;

&lt;p&gt;Those discontinuities create problems for many forms of mathematical modelling, since their models are based upon continuous functions. For instance, many price oscillations look like periodic functions, but when a discontinuity is found, any harmonic analysis becomes troublesome.&lt;/p&gt;

&lt;p&gt;Actually, a trend can also be troublesome to the fitting of periodic functions to financial data. But in this case, fitting a polynomial of low grade to the data can filter the trend and then a periodic function series can be fitted to the residuals, the difference between the fitted polynomial and the original data.&lt;/p&gt;

&lt;p&gt;The purpose of this suite of articles is to present a simple method to eliminate jumps from the observed data. Of course, when reconstructing the fitted data, the discontinuity will be added back.&lt;/p&gt;

&lt;p&gt;Only very basic knowledge of Python and time series are needed as most concepts will be explained with care and references to longer tutorials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;p&gt;This one, the 1st of 5 short articles, will introduce the general concepts for the solution, the &lt;a href="https://dev.to/hilton_fernandes_eaac26ab/leveling-with-cluster-analysis-in-python-basic-python-concepts-1n6"&gt;2nd one&lt;/a&gt; will present basic Python concepts and techniques to be used in the solution, the 3rd one will present a solution implemented in Python, the 4th article will add a sinusoidal decomposition of the data after the filtering of the solution, and the 5th and last one will use all the elements to address a real problem in cryptocurrencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cluster analysis as a means to group similar data
&lt;/h2&gt;

&lt;p&gt;Cluster analysis is a well-known technique for grouping data elements based on their similarities. In a metric space, similarity means smaller distances. There are several ways to devise the groups or clusters of data, and one of the simplest is called &lt;a href="https://en.wikipedia.org/wiki/K-means_clustering" rel="noopener noreferrer"&gt;k-means clustering&lt;/a&gt;. In very few words, it creates clusters by assigning a mean average of the coordinates to a point, that's a &lt;em&gt;centroid&lt;/em&gt;. Through these articles we shall use only k-means clustering.&lt;/p&gt;

&lt;p&gt;The following image is a typical two-dimensional representation of two groups.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hwo0a10z279kdqhxm5j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hwo0a10z279kdqhxm5j.jpg" alt=" " width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The points are in blue, and the centroids are in red.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cluster analysis in a curve
&lt;/h2&gt;

&lt;p&gt;Since the k-means clustering is based upon the distance of points, an interesting effect will happen when the points are connected in a curve; therefore, they are much closer to each other than the points dispersed in a cloud, like in the previous image.&lt;/p&gt;

&lt;p&gt;Please consider the following image that shows a time series with a discontinuity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vx61npnjasazb722kxj.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vx61npnjasazb722kxj.jpeg" alt="A time series with a discontinuity" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a k-means cluster analysis is applied to it, the centroids of the clusters are shown in red.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4paveeq32asnqw1ua83p.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4paveeq32asnqw1ua83p.jpeg" alt="A time series with clusters in the discontinuity" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's easy to see that the there are two groups are in different levels, as shown in the following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffe1jhj3xf2wrkktuzksx.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffe1jhj3xf2wrkktuzksx.jpeg" alt="Levels in the time series with discontinuity" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Group 2 is around the green line, while the Group 1 is around the red line.  &lt;/p&gt;

&lt;p&gt;Then to eliminate the discontinuity, it's enough to lower the Group 1 to the level of the Group 2.  That is: to subtract from the points &lt;code&gt;y&lt;/code&gt; coordinate the difference between the level of the two groups.&lt;/p&gt;

&lt;p&gt;That can be shown in the following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8c8sq9sxiucspp46j4yx.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8c8sq9sxiucspp46j4yx.jpeg" alt="Unification of the two clusters" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now no differences can be seen in the two groups of points.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next step
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://dev.to/hilton_fernandes_eaac26ab/leveling-with-cluster-analysis-in-python-basic-python-concepts-1n6"&gt;next article&lt;/a&gt; in this suit will introduce the basic Python concepts needed to create the 1st of the images presented here, and also used in the other articles.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>python</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
