diff --git a/Instructions/Labs/02-analyze-spark.md b/Instructions/Labs/02-analyze-spark.md index b4b42a3..9de2501 100644 --- a/Instructions/Labs/02-analyze-spark.md +++ b/Instructions/Labs/02-analyze-spark.md @@ -4,587 +4,588 @@ lab: module: Use Apache Spark to work with files in a lakehouse --- -# Analisar dados com Apache Spark +# Analisar dados com Apache Spark no Fabric -O Apache Spark é um mecanismo de código aberto para processamento de dados distribuído e é amplamente usado para explorar, processar e analisar grandes volumes de dados no data lake storage. O Spark está disponível como uma opção de processamento em vários produtos de plataforma de dados, incluindo o Azure HDInsight, o Azure Databricks, o Azure Synapse Analytics e o Microsoft Fabric. Um dos benefícios do Spark é o suporte a uma ampla variedade de linguagens de programação, incluindo Java, Scala, Python e SQL, tornando o Spark uma solução muito flexível para cargas de trabalho de processamento de dados, incluindo limpeza e processamento de dados, análise estatística e machine learning, análise e visualização de dados. +Neste laboratório, você ingerirá dados no lakehouse do Fabric e usará o PySpark para ler e analisar os dados. -Este laboratório levará aproximadamente **45** minutos para ser concluído. +Este laboratório levará aproximadamente 45 minutos para ser concluído. -> **Observação**: Você precisará uma [avaliação gratuita do Microsoft Fabric](https://learn.microsoft.com/fabric/get-started/fabric-trial) para concluir este exercício. +## Pré-requisitos -## Criar um workspace +* Uma [avaliação do Microsoft Fabric](/fabric/get-started/fabric-trial#start-the-fabric-capacity-trial). -Antes de trabalhar com os dados no Fabric, crie um workspace com a avaliação do Fabric habilitada. +## Criar um workspace -1. Na [página inicial do Microsoft Fabric](https://app.fabric.microsoft.com/home?experience=fabric) no `https://app.fabric.microsoft.com/home?experience=fabric`, selecione **Engenharia de Dados do Synapse**. -1. Na barra de menus à esquerda, selecione **Workspaces** (o ícone é semelhante a 🗇). -1. Crie um workspace com um nome de sua escolha, selecionando um modo de licenciamento na seção **Avançado** que inclua a capacidade do Fabric (*Avaliação*, *Premium* ou *Malha*). -1. Quando o novo workspace for aberto, ele estará vazio. +Antes de trabalhar com dados no Fabric, você precisa criar um espaço de trabalho. - ![Captura de tela de um espaço de trabalho vazio no Fabric.](./Images/new-workspace.png) +1. Na home page do [Microsoft Fabric](https://app.fabric.microsoft.com) em https://app.fabric.microsoft.com, escolha a experiência **Engenharia de Dados**. +1. Na barra de navegação à esquerda, selecione **Espaços de trabalho** (🗇) e **Novo espaço de trabalho**. +1. Dê um nome ao novo espaço de trabalho e, na seção **Avançado**, escolha o Modo de licenciamento apropriado. Se você tiver iniciado uma avaliação do Microsoft Fabric, escolha Avaliação. +1. Clique em **Aplicar** para criar um espaço de trabalho vazio. + +![Imagem da tela dos arquivos CSV carregados em um novo espaço de trabalho do Fabric.](Images/uploaded-files.jpg) ## Criar um lakehouse e carregar arquivos -Agora que você tem um espaço de trabalho, é hora de criar um data lakehouse para os arquivos de dados que serão analisados. +Agora que tem um espaço de trabalho, você pode criar um lakehouse para seus arquivos de dados. No novo workspace, clique em **Novo** e **Lakehouse**. Dê um nome ao lakehouse e clique em **Criar**. Após um pequeno atraso, um novo lakehouse será criado. -1. Na home page da **Engenharia de Dados do Synapse**, crie um **Lakehouse** com um nome de sua escolha. +Você já pode ingerir dados no lakehouse. Há várias maneiras de fazer isso, mas por ora, você baixará uma pasta de arquivos de texto no computador local (ou na VM de laboratório, se aplicável) e fará seu upload no lakehouse. - Após alguns minutos, um lakehouse vazio será criado. Você precisa ingerir alguns dados no data lakehouse para análise. Há várias maneiras de fazer isso, mas neste exercício, você apenas baixará e extrairá uma pasta de arquivos de texto no computador local (ou na VM de laboratório, se aplicável) e os carregará no lakehouse. +1. Baixe os arquivos de dados em https://github.com/MicrosoftLearning/dp-data/raw/main/orders.zip. +1. Extraia o arquivo compactado e verifique se você tem uma pasta chamada *orders* com três arquivos CSV: 2019.csv, 2020.csv e 2021.csv. +1. Volte para o novo lakehouse. No painel do **Explorer**, clique no menu de reticências (**...**) ao lado da pasta **Arquivos** e clique em **Carregar** e **Carregar pasta**. Navegue até a pasta de pedidos em seu computador local (ou VM de laboratório, se aplicável) e clique em **Carregar**. +1. Depois que os arquivos forem carregados, expanda **Arquivos** e clique na pasta **orders**. Verifique se os arquivo CSV foram carregados, conforme mostrado aqui: -1. Baixe e extraia os [arquivos de dados](https://github.com/MicrosoftLearning/dp-data/raw/main/orders.zip) deste exercício em `https://github.com/MicrosoftLearning/dp-data/raw/main/orders.zip`. +![Imagem de tela de um novo espaço de trabalho do Fabric.](Images/new-workspace.jpg) -1. Depois de extrair o arquivo compactado, verifique se você tem uma pasta chamada **orders** que contém arquivos CSV chamados **2019.csv**, **2020.csv** e **2021.csv**. -1. Volte à guia do navegador da Web que contém o lakehouse e, no menu **…** da pasta **Arquivos** no painel do **Explorer**, selecione **Carregar** e **Carregar pasta** e carregue a pasta **orders** do computador local (ou da VM de laboratório, se aplicável) para o lakehouse. -1. Depois que os arquivos forem carregados, expanda **Arquivos**, selecione a pasta **orders** e verifique se os arquivos CSV foram carregados, conforme mostrado aqui: +## Criar um notebook - ![Captura de tela dos arquivos carregados em um lakehouse.](./Images/uploaded-files.png) +Agora você pode criar um notebook do Fabric para trabalhar com seus dados. Os notebooks fornecem um ambiente interativo no qual você pode escrever e executar código. -## Criar um notebook +1. Escolha o seu espaço de trabalho e clique em **Novo** e **Notebook**. Após alguns segundos, um novo notebook que contém uma só célula será aberto. Os notebooks são compostos por uma ou mais células que podem conter um código ou um markdown (texto formatado). +1. O Fabric atribui um nome a cada notebook criado, como Bloco de Notebook 1, Notebook 2, etc. Clique no painel de nome acima da guia **Página Inicial** no menu para alterar o nome para algo mais descritivo. +1. Selecione a primeira célula (que atualmente é uma célula de código) e, na barra de ferramentas no canto superior direito, use o botão **M↓** para convertê-la em uma célula Markdown. O texto contido na célula será então exibido como texto formatado. +1. Use o botão 🖉 (Editar) para alternar a célula para o modo de edição e modifique o Markdown como mostrado abaixo. + +```markdown +# Sales order data exploration +Use this notebook to explore sales order data +``` +![Imagem de tela de um notebook Fabric com uma célula Markdown.](Images/name-notebook-markdown.jpg) -Para trabalhar com os dados no Apache Spark, você pode criar um *notebook*. Os notebooks fornecem um ambiente interativo no qual você pode escrever e executar o código (em várias linguagens) e adicionar anotações para documentá-lo. +Quando terminar, clique em qualquer lugar no notebook fora da célula para parar de editá-lo e ver o Markdown renderizado. -1. Na **Home page**, ao exibir o conteúdo da pasta **orders** no data lake, no menu **Abrir notebook**, selecione **Novo notebook**. - Após alguns segundos, um novo notebook que contém uma só *célula* será aberto. Os notebooks são compostos por uma ou mais células que podem conter um *código* ou um *markdown* (texto formatado). +## Criar um DataFrame -2. Selecione a primeira célula (que atualmente é uma célula de *código*) e na barra de ferramentas dinâmica no canto superior direito, use o botão **M↓** para converter a célula em uma célula *markdown*. +Agora que você criou um espaço de trabalho, um lakehouse e um notebook, você pode trabalhar com seus dados. Você usará o PySpark, que é a linguagem padrão para notebooks do Fabric, e a versão do Python otimizada para o Spark. - Quando a célula for alterada para uma célula markdown, o texto que ela contém será renderizado. +**OBSERVAÇÃO:** os notebooks do Fabric aceitam várias linguagens de programação, incluindo Scala, R e Spark SQL. -3. Use o botão **🖉** (Editar) para alternar a célula para o modo de edição e modifique o markdown da seguinte maneira: +1. Selecione seu novo espaço de trabalho na barra à esquerda. Você verá uma lista de itens contidos no espaço de trabalho, incluindo seu lakehouse e notebook. +2. Selecione o lakehouse para exibir o painel Explorer, incluindo a pasta **orders**. +3. No menu superior, clique em **Abrir notebook**, **Notebook existente** e, em seguida, abra o notebook criado anteriormente. O notebook abrirá ao lado do painel Explorer. Expanda Lakehouses, expanda a lista Arquivos e selecione a pasta "orders". Os arquivos CSV que você carregou são listados ao lado do editor de notebook, desta maneira: - ``` - # Sales order data exploration +![Imagem da tela de arquivos csv na exibição do Explorer.](Images/explorer-notebook-view.jpg) - Use the code in this notebook to explore sales order data. - ``` +4. No menu ... de 2019.csv, selecione **Carregar dados** > **Spark**. O código é gerado automaticamente em uma nova célula de código: -4. Clique em qualquer lugar no notebook fora da célula para parar de editá-lo e ver o markdown renderizado. +```python +df = spark.read.format("csv").option("header","true").load("Files/orders/2019.csv") +# df now is a Spark DataFrame containing CSV data from "Files/orders/2019.csv". +display(df) +``` -## Carregar dados em um dataframe +**Dica:** você pode ocultar os painéis Explorer do lakehouse à esquerda usando os ícones «. Isso dá mais espaço para o notebook. -Agora você está pronto para executar o código que carrega os dados em um *dataframe*. Os dataframes no Spark são semelhantes aos dataframes do Pandas no Python e fornecem uma estrutura comum para trabalhar com os dados em linhas e colunas. +5. Clique em ▷ **Executar célula** à esquerda da célula para executar o código. -> **Observação**: o Spark dá suporte a várias linguagens de codificação, incluindo Scala, Java e outras. Neste exercício, usaremos o *PySpark*, que é uma variante otimizada para Spark do Python. O PySpark é uma das linguagens mais usadas no Spark e é a linguagem padrão nos notebooks do Fabric. +**OBSERVAÇÃO**: como esta é a primeira vez que você executa o código Spark, uma sessão do Spark será iniciada. Isso pode levar alguns segundos ou mais. As execuções subsequentes na mesma sessão serão mais rápidas. -1. Com o notebook visível, no painel do **Explorer** expanda **Lakehouses** e, a seguir, expanda a lista **Arquivos** para o seu lakehouse e selecione a pasta **Pedidos** para que os arquivos CSV sejam listados ao lado do editor do notebook, assim: +6. Quando o código da célula for concluído, analise a saída abaixo da célula, que deve ser semelhante a: + +![Imagem da tela mostrando código e dados gerados automaticamente.](Images/auto-generated-load.jpg) - ![Captura de tela de um notebook com um painel Arquivos.](./Images/notebook-files.png) +7. A saída mostra os dados do arquivo 2019.csv exibidos em linhas e as colunas. Perceba que os cabeçalhos das colunas contêm a primeira linha dos dados. Para corrigir isso, você precisa modificar a primeira linha do código da seguinte maneira: -1. No menu **…** de **2019.csv**, selecione **Carregar dados** > **Spark**. Uma nova célula de código que contém o seguinte código deve ser adicionada ao notebook: +```python +df = spark.read.format("csv").option("header","false").load("Files/orders/2019.csv") +``` - ```python - df = spark.read.format("csv").option("header","true").load("Files/orders/2019.csv") - # df now is a Spark DataFrame containing CSV data from "Files/orders/2019.csv". - display(df) - ``` +8. Execute o código novamente, para que o DataFrame identifique corretamente a primeira linha como dados. Perceba que os nomes das colunas agora mudaram para _c0, _c1, etc. - > **Dica**: oculte os painéis do Lakehouse Explorer à esquerda usando os ícones **<<** . Isso ajudará você a se concentrar no notebook. +9. Nomes de coluna descritivos ajudam você a entender os dados. Para criar nomes de coluna significativos, você precisa definir o esquema e os tipos de dados. Você também precisa importar um conjunto padrão de tipos SQL do Spark para definir os tipos de dados. Substitua o código existente pelo seguinte: -1. Use o botão **▷ Executar célula** à esquerda da célula para executá-la. +```python +from pyspark.sql.types import * - > **Observação**: como esta é a primeira vez que você executa qualquer código Spark, uma sessão do Spark precisa ser iniciada. Isso significa que a primeira execução na sessão pode levar um minuto para ser concluída. As execuções seguintes serão mais rápidas. +orderSchema = StructType([ + StructField("SalesOrderNumber", StringType()), + StructField("SalesOrderLineNumber", IntegerType()), + StructField("OrderDate", DateType()), + StructField("CustomerName", StringType()), + StructField("Email", StringType()), + StructField("Item", StringType()), + StructField("Quantity", IntegerType()), + StructField("UnitPrice", FloatType()), + StructField("Tax", FloatType()) + ]) -1. Quando o comando de célula for concluído, analise a saída abaixo da célula, que deve ser semelhante a essa: +df = spark.read.format("csv").schema(orderSchema).load("Files/orders/2019.csv") - | Índice | SO43701 | 11 | 2019-07-01 | Christy Zhu | christy12@adventure-works.com | Mountain-100 Silver, 44 | 16 | 3399.99 | 271.9992 | - | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | - | 1 | SO43704 | 1 | 2019-07-01 | Julio Ruiz | julio1@adventure-works.com | Mountain-100 Black, 48 | 1 | 3374.99 | 269.9992 | - | 2 | SO43705 | 1 | 2019-07-01 | Curtis Lu | curtis9@adventure-works.com | Mountain-100 Silver, 38 | 1 | 3399.99 | 271.9992 | - | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | +display(df) - A saída mostra as linhas e as colunas de dados do arquivo 2019.csv. No entanto, observe que os cabeçalhos de coluna não parecem corretos. O código padrão usado para carregar os dados em um dataframe pressupõe que o arquivo CSV inclua os nomes de coluna na primeira linha, mas nesse caso o arquivo CSV inclui apenas os dados sem informações de cabeçalho. +``` +10. Execute a célula e analise a saída: -1. Modifique o código para definir a opção **cabeçalho** como **false** da seguinte maneira: +![Imagem da tela do código com esquema definido e dados.](Images/define-schema.jpg) - ```python - df = spark.read.format("csv").option("header","false").load("Files/orders/2019.csv") - # df now is a Spark DataFrame containing CSV data from "Files/orders/2019.csv". - display(df) - ``` +11. Esse DataFrame só inclui os dados do arquivo 2019.csv. Modifique o código para que o caminho do arquivo use um curinga * para ler todos os dados na pasta orders: -1. Execute a célula novamente e analise a saída, que deve ser semelhante à esta: +```python +from pyspark.sql.types import * - | Índice | _c0 | _c1 | _c2 | _c3 | _c4 | _c5 | _c6 | _c7 | _c8 | - | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | - | 1 | SO43701 | 11 | 2019-07-01 | Christy Zhu | christy12@adventure-works.com | Mountain-100 Silver, 44 | 16 | 3399.99 | 271.9992 | - | 2 | SO43704 | 1 | 2019-07-01 | Julio Ruiz | julio1@adventure-works.com | Mountain-100 Black, 48 | 1 | 3374.99 | 269.9992 | - | 3 | SO43705 | 1 | 2019-07-01 | Curtis Lu | curtis9@adventure-works.com | Mountain-100 Silver, 38 | 1 | 3399.99 | 271.9992 | - | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | +orderSchema = StructType([ + StructField("SalesOrderNumber", StringType()), + StructField("SalesOrderLineNumber", IntegerType()), + StructField("OrderDate", DateType()), + StructField("CustomerName", StringType()), + StructField("Email", StringType()), + StructField("Item", StringType()), + StructField("Quantity", IntegerType()), + StructField("UnitPrice", FloatType()), + StructField("Tax", FloatType()) + ]) - Agora, o dataframe inclui corretamente a primeira linha como valores de dados, mas os nomes de colunas são gerados automaticamente e não são muito úteis. Para entender os dados, você precisa definir explicitamente o esquema e o tipo de dados corretos para os valores de dados no arquivo. +df = spark.read.format("csv").schema(orderSchema).load("Files/orders/*.csv") -1. Modifique o código da seguinte maneira para definir um esquema e aplicá-lo ao carregar os dados: +display(df) +``` - ```python - from pyspark.sql.types import * +12. Ao executar o código modificado, você verá as vendas de 2019, 2020 e 2021. Apenas um subconjunto das linhas é exibido, portanto, talvez você não veja as linhas de todos os anos. - orderSchema = StructType([ - StructField("SalesOrderNumber", StringType()), - StructField("SalesOrderLineNumber", IntegerType()), - StructField("OrderDate", DateType()), - StructField("CustomerName", StringType()), - StructField("Email", StringType()), - StructField("Item", StringType()), - StructField("Quantity", IntegerType()), - StructField("UnitPrice", FloatType()), - StructField("Tax", FloatType()) - ]) +**OBSERVAÇÃO:** Você pode ocultar ou exibir a saída de uma célula clicando em ... ao lado do resultado. Isso facilita o trabalho em um notebook. - df = spark.read.format("csv").schema(orderSchema).load("Files/orders/2019.csv") - display(df) - ``` +## Explorar dados em um DataFrame -1. Execute a célula modificada e analise a saída, que deve ser semelhante à esta: +O objeto DataFrame fornece funcionalidades adicionais, como a capacidade de filtrar, agrupar e manipular dados. - | Índice | SalesOrderNumber | SalesOrderLineNumber | OrderDate | CustomerName | Email | Item | Quantidade | UnitPrice | Imposto | - | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | - | 1 | SO43701 | 11 | 2019-07-01 | Christy Zhu | christy12@adventure-works.com | Mountain-100 Silver, 44 | 16 | 3399.99 | 271.9992 | - | 2 | SO43704 | 1 | 2019-07-01 | Julio Ruiz | julio1@adventure-works.com | Mountain-100 Black, 48 | 1 | 3374.99 | 269.9992 | - | 3 | SO43705 | 1 | 2019-07-01 | Curtis Lu | curtis9@adventure-works.com | Mountain-100 Silver, 38 | 1 | 3399.99 | 271.9992 | - | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | +### Filtrar um DataFrame - Agora, o dataframe inclui os nomes de colunas corretos (além do **Índice**, que é uma coluna interna em todos os dataframes com base na posição ordinal de cada linha). Os tipos de dados das colunas são especificados por meio de um conjunto padrão de tipos definidos na biblioteca do Spark SQL, que foram importados no início da célula. +1. Adicione uma célula de código clicando em **+ Código**, que aparece quando você passa o mouse acima ou abaixo da célula atual ou da respectiva saída. Como alternativa, no menu da faixa de opções, selecione **Editar** e **+ Adicionar** célula de código. -1. O dataframe só inclui os dados do arquivo **2019.csv**. Modifique o código para que o caminho do arquivo use um curinga \* para ler os dados do pedido de vendas de todos os arquivos da pasta **orders**: +2. O código a seguir filtrará os dados para que apenas duas colunas sejam retornadas. Ele também usa *count* e *distinct* para resumir o número de registros: - ```python - from pyspark.sql.types import * +```python +customers = df['CustomerName', 'Email'] - orderSchema = StructType([ - StructField("SalesOrderNumber", StringType()), - StructField("SalesOrderLineNumber", IntegerType()), - StructField("OrderDate", DateType()), - StructField("CustomerName", StringType()), - StructField("Email", StringType()), - StructField("Item", StringType()), - StructField("Quantity", IntegerType()), - StructField("UnitPrice", FloatType()), - StructField("Tax", FloatType()) - ]) +print(customers.count()) +print(customers.distinct().count()) - df = spark.read.format("csv").schema(orderSchema).load("Files/orders/*.csv") - display(df) - ``` +display(customers.distinct()) +``` -1. Execute a célula de código modificada e analise a saída, que agora incluirá as vendas de 2019, 2020 e 2021. +3. Execute o código e analise a saída: - **Observação**: somente um subconjunto das linhas é exibido, ou seja, talvez você não consiga ver exemplos de todos os anos. +* O código cria um novo DataFrame chamado **customers**, que contém um subconjunto de colunas do DataFrame **df** original. Ao executar uma transformação DataFrame, você não modifica o DataFrame original, mas retorna um novo. +* Outra maneira de obter o mesmo resultado é usar o método select: -## Explorar os dados em um dataframe +``` +customers = df.select("CustomerName", "Email") +``` -O objeto de dataframe inclui uma ampla variedade de funções que você pode usar para filtrar, agrupar e processar os dados que ele contém. +* As funções *count* e *distinct* do DataFrame são usadas para fornecer totais do número de clientes e de clientes exclusivos. -### Filtrar um dataframe +4. Modifique a primeira linha do código usando *select* com uma função *where* da seguinte maneira: -1. Adicione uma nova célula de código usando o link **+ Código** que aparece ao mover o cursos sob o lado esquerdo da saída da célula atual (ou na barra de menu, na guia **Editar**, selecione **+ Adicionar célula de código**). A seguir insira nele o seguinte código: +```python +customers = df.select("CustomerName", "Email").where(df['Item']=='Road-250 Red, 52') +print(customers.count()) +print(customers.distinct().count()) - ```Python - customers = df['CustomerName', 'Email'] - print(customers.count()) - print(customers.distinct().count()) - display(customers.distinct()) - ``` +display(customers.distinct()) +``` -2. Execute a nova célula de código e analise os resultados. Observe os seguintes detalhes: - - Quando você executa uma operação em um dataframe, o resultado é um novo dataframe (nesse caso, um dataframe **customers** é criado pela seleção de um subconjunto específico de colunas do dataframe **df**) - - Os dataframes fornecem funções como **count** e **distinct** que podem ser usadas para resumir e filtrar os dados que eles contêm. - - A sintaxe `dataframe['Field1', 'Field2', ...]` é uma forma abreviada de definir um subconjunto de colunas. Você também pode usar o método **select**, para que a primeira linha do código acima possa ser escrita como `customers = df.select("CustomerName", "Email")` +5. Execute o código modificado para selecionar apenas os clientes que compraram o produto Road-250 Red, 52. Você pode "encadear" várias funções para que a saída de uma função se torne a entrada da próxima. Nesse caso, o DataFrame criado pelo método *select* é o DataFrame de origem do método **where** usado para aplicar critérios de filtragem. -3. Modifique o código da seguinte maneira: +### Agregar e agrupar dados em um DataFrame + +1. Adicione uma célula de código e insira o seguinte código: - ```Python - customers = df.select("CustomerName", "Email").where(df['Item']=='Road-250 Red, 52') - print(customers.count()) - print(customers.distinct().count()) - display(customers.distinct()) - ``` +```python +productSales = df.select("Item", "Quantity").groupBy("Item").sum() -4. Execute o código modificado para visualizar os clientes que compraram o produto *Road-250 Red, 52*. Observe que você pode "encadear" várias funções para que a saída de uma função se torne a entrada da próxima. Nesse caso, o dataframe criado pelo método **select** é o dataframe de origem do método **where** usado para aplicar os critérios de filtragem. +display(productSales) +``` -### Agregar e agrupar dados em um dataframe +2. Execute o código. Observe que os resultados mostram a soma das quantidades de pedido agrupadas por produto. O método *groupBy* agrupa as linhas por Item, e a função de agregação *sum* subsequente é aplicada às colunas numéricas restantes, nesse caso, *Quantidade*. -1. Adicione uma nova célula de código ao notebook e insira o seguinte código nela: +3. Adicione outra célula de código ao notebook e insira o seguinte código nela: - ```Python - productSales = df.select("Item", "Quantity").groupBy("Item").sum() - display(productSales) - ``` +```python +from pyspark.sql.functions import * -2. Execute a célula de código que você adicionou e observe que os resultados mostram a soma das quantidades de pedidos agrupadas por produto. O método **groupBy** agrupa as linhas por *Item*, e a função de agregação de **soma** seguinte é aplicada a todas as colunas numéricas restantes (nesse caso, *Quantidade*) +yearlySales = df.select(year(col("OrderDate")).alias("Year")).groupBy("Year").count().orderBy("Year") -3. Adicione outra nova célula de código ao notebook e insira o seguinte código nela: +display(yearlySales) +``` - ```Python - from pyspark.sql.functions import * +4. Execute a célula. Examine a saída. Os resultados mostram o número de pedidos de vendas por ano: - yearlySales = df.select(year("OrderDate").alias("Year")).groupBy("Year").count().orderBy("Year") - display(yearlySales) - ``` +* A instrução *import* permite que você use a biblioteca SQL do Spark. +* O método *select* é usado com uma função year do SQL para extrair o componente de ano do campo *OrderDate*. +* O método *alias* para atribuir um nome de coluna ao valor de ano extraído. +* O método *groupBy* agrupa os dados pela coluna Year derivada. +* A contagem de linhas em cada grupo é calculada antes de o método *orderBy* ser usado para classificar o DataFrame resultante. -4. Execute a célula de código que você adicionou e observe que os resultados mostram o número de pedidos de vendas por ano. Observe que o método **select** inclui uma função SQL **year** para extrair o componente de ano do campo *OrderDate* (razão pela qual o código inclui uma instrução **import** para importar funções da biblioteca do Spark SQL). Em seguida, ele usa um método de **alias** para atribuir um nome de coluna ao valor de ano extraído. Em seguida, os dados são agrupados pela coluna *Year* derivada, e a contagem de linhas em cada grupo é calculada antes de finalmente o método **orderBy** ser usado para classificar o dataframe resultante. +![Imagem de tela mostrando os resultados da agregação e agrupamento de dados em um DataFrame.](Images/spark-sql-dataframe.jpg) ## Usar o Spark para transformar arquivos de dados -Uma tarefa comum para engenheiros de dados é ingerir os dados em uma estrutura ou em um formato específico e transformá-los para processamento ou análise downstream adicionais. +Uma tarefa comum para engenheiros e cientistas de dados é transformar os dados para processamento ou análise downstream adicionais. -### Usar métodos e funções de dataframe para transformar dados +### Usar métodos e funções de DataFrame para transformar dados -1. Adicione outra nova célula de código ao notebook e insira o seguinte código nela: +1. Adicione uma célula de código ao notebook e insira o seguinte: - ```Python - from pyspark.sql.functions import * +```python +from pyspark.sql.functions import * - ## Create Year and Month columns - transformed_df = df.withColumn("Year", year(col("OrderDate"))).withColumn("Month", month(col("OrderDate"))) +# Create Year and Month columns +transformed_df = df.withColumn("Year", year(col("OrderDate"))).withColumn("Month", month(col("OrderDate"))) - # Create the new FirstName and LastName fields - transformed_df = transformed_df.withColumn("FirstName", split(col("CustomerName"), " ").getItem(0)).withColumn("LastName", split(col("CustomerName"), " ").getItem(1)) +# Create the new FirstName and LastName fields +transformed_df = transformed_df.withColumn("FirstName", split(col("CustomerName"), " ").getItem(0)).withColumn("LastName", split(col("CustomerName"), " ").getItem(1)) - # Filter and reorder columns - transformed_df = transformed_df["SalesOrderNumber", "SalesOrderLineNumber", "OrderDate", "Year", "Month", "FirstName", "LastName", "Email", "Item", "Quantity", "UnitPrice", "Tax"] +# Filter and reorder columns +transformed_df = transformed_df["SalesOrderNumber", "SalesOrderLineNumber", "OrderDate", "Year", "Month", "FirstName", "LastName", "Email", "Item", "Quantity", "UnitPrice", "Tax"] - # Display the first five orders - display(transformed_df.limit(5)) - ``` +# Display the first five orders +display(transformed_df.limit(5)) +``` -2. Execute o código para criar um dataframe com base nos dados do pedido original com as seguintes transformações: - - Adicione as colunas **Year** e **Month** com base na coluna **OrderDate**. - - Adicione as colunas **FirstName** e **LastName** com base na coluna **CustomerName**. - - Filtre e reordene as colunas, removendo a coluna **CustomerName**. +2. Execute a célula. Um novo DataFrame com base nos dados do pedido original com as seguintes transformações: + +- Colunas Year e Month adicionadas com base na coluna OrderDate. +- Colunas FirstName e LastName adicionadas com base na coluna CustomerName. +- As colunas são filtradas e reordenadas, e a coluna CustomerName é removida. 3. Analise a saída e verifique se as transformações foram feitas nos dados. - Use todo o potencial da biblioteca do Spark SQL para transformar os dados filtrando linhas, derivando, removendo, renomeando colunas e aplicando outras modificações de dados necessárias. +Você pode usar a biblioteca do Spark SQL para transformar os dados filtrando linhas, derivando, removendo, renomeando colunas e aplicando outras modificações de dados. - > **Dica**: confira a [documentação do dataframe do Spark](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/dataframe.html) para saber mais sobre os métodos do objeto Dataframe. +>[!TIP] +> Confira a documentação do [dataframe do Apache Spark](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/dataframe.html) para saber mais sobre o objeto Dataframe. ### Salvar os dados transformados -1. Adicione uma nova célula com o seguinte código para salvar o dataframe transformado no formato Parquet (substituindo os dados se eles já existirem): +A esta altura, talvez você queira salvar os dados transformados para usá-los para análise posterior. + +O *Parquet* é um formato popular de armazenamento de dados porque armazena dados com eficiência e é compatível com a maioria dos sistemas de análise de dados em grande escala. Na verdade, às vezes, o requisito de transformação de dados é converter dados de um formato, como CSV, em Parquet. + +1. Para salvar o DataFrame transformado no formato Parquet, adicione uma célula de código e adicione o seguinte código: - ```Python - transformed_df.write.mode("overwrite").parquet('Files/transformed_data/orders') - print ("Transformed data saved!") - ``` +```python +transformed_df.write.mode("overwrite").parquet('Files/transformed_data/orders') - > **Observação**: normalmente, o formato *Parquet* é preferencial para os arquivos de dados que você usará para análise ou ingestão posterior em um repositório analítico. O Parquet é um formato muito eficiente que é compatível com a maioria dos sistemas de análise de dados em grande escala. Na verdade, às vezes, seu requisito de transformação de dados pode ser apenas converter dados de outro formato (como CSV) em Parquet. +print ("Transformed data saved!") +``` -2. Execute a célula e aguarde a mensagem indicando que os dados foram salvos. Em seguida, no painel **Lakehouses** do lado esquerdo, no menu **…** do nó **Arquivos**, selecione **Atualizar** e selecione a pasta **transformed_data** para verificar se contém uma nova pasta chamada **pedidos**, que, por sua vez, contém um ou mais arquivos Parquet. +2. Execute a célula e aguarde a mensagem indicando que os dados foram salvos. Em seguida, no painel do Lakehouses à esquerda, no menu ... do nó Arquivos, clique em **Atualizar**. Escolha a pasta transformed_data para verificar se ela contém uma nova pasta chamada orders, que por sua vez contém um ou mais arquivos Parquet. - ![Captura de tela de uma pasta que contém os arquivos Parquet.](./Images/saved-parquet.png) +3. Adicione uma célula com o seguinte código: -3. Adicione uma nova célula com o seguinte código para carregar um novo dataframe dos arquivos Parquet na pasta **transformed_data/orders**: +```python +orders_df = spark.read.format("parquet").load("Files/transformed_data/orders") +display(orders_df) +``` - ```Python - orders_df = spark.read.format("parquet").load("Files/transformed_data/orders") - display(orders_df) - ``` +4. Execute a célula. Um novo DataFrame é criado a partir dos arquivos parquet na pasta *transformed_data/orders*. Verifique se os resultados mostram os dados do pedido que foram carregados a partir dos arquivos Parquet. -4. Execute a célula e verifique se os resultados mostram os dados do pedido que foram carregados dos arquivos Parquet. +![Imagem da tela mostrando arquivos Parquet.](Images/parquet-files.jpg) ### Salvar os dados em arquivos particionados -1. Adicione uma nova célula com o código a seguir, que salva o dataframe, particionando os dados por **Year** e **Month**: +Ao lidar com grandes volumes de dados, o particionamento pode melhorar significativamente o desempenho e facilitar a filtragem de dados. - ```Python - orders_df.write.partitionBy("Year","Month").mode("overwrite").parquet("Files/partitioned_data") - print ("Transformed data saved!") - ``` +1. Adicione uma célula com o código para salvar o dataframe, particionando os dados por Year e Month: -2. Execute a célula e aguarde a mensagem indicando que os dados foram salvos. Em seguida, no painel **Lakehouses** do lado esquerdo, no menu **…** do nó **Arquivos**, selecione **Atualizar**e expanda a pasta **Pedidos particionados** para verificar se contém uma hierarquia de pastas chamada **Ano=* xxxx***, cada uma contendo pastas chamadas **Mês=* xxxx***. Cada pasta mensal contém um arquivo Parquet com os pedidos desse mês. +```python +orders_df.write.partitionBy("Year","Month").mode("overwrite").parquet("Files/partitioned_data") - ![Captura de tela de uma hierarquia de arquivos de dados particionados.](./Images/partitioned-files.png) +print ("Transformed data saved!") +``` - Particionar arquivos de dados é uma forma comum de otimizar o desempenho ao lidar com grandes volumes de dados. Essa técnica pode aprimorar consideravelmente o desempenho e facilitar a filtragem de dados. +2. Execute a célula e aguarde a mensagem indicando que os dados foram salvos. Em seguida, no painel do Lakehouses à esquerda, no menu ... do nó Arquivos, clique em **Atualizar** e expanda a pasta partitioned_orders para verificar que ela contém uma hierarquia de pastas chamada *Year=xxxx*, cada uma contendo pastas chamadas *Month=xxxx*. Cada pasta mensal contém um arquivo Parquet com os pedidos desse mês. -3. Adicione uma nova célula com o seguinte código para carregar um novo dataframe por meio do arquivo **orders.parquet**: +![Imagem da tela mostrando dados particionados por Year e Month.](Images/partitioned-data.jpg) - ```Python - orders_2021_df = spark.read.format("parquet").load("Files/partitioned_data/Year=2021/Month=*") - display(orders_2021_df) - ``` +3. Adicione uma nova célula com o seguinte código para carregar um novo DataFrame a partir do arquivo orders.parquet: -4. Execute a célula e verifique se os resultados mostram os dados do pedido de vendas em 2021. Observe que as colunas de particionamento especificadas no caminho (**Year** e **Month**) não estão incluídas no dataframe. +```python +orders_2021_df = spark.read.format("parquet").load("Files/partitioned_data/Year=2021/Month=*") + +display(orders_2021_df) +``` + +4. Execute a célula e verifique se os resultados mostram os dados do pedido de vendas em 2021. Perceba que as colunas de particionamento especificadas no caminho (Year e Month) não estão incluídas no DataFrame. ## Trabalhar com tabelas e o SQL -Como você viu, os métodos nativos do objeto de dataframe permitem que você consulte e analise os dados de um arquivo com bastante eficiência. No entanto, muitos analistas de dados se sentem mais à vontade em trabalhar com tabelas que eles podem consultar usando a sintaxe SQL. O Spark fornece um *metastore* no qual você pode definir tabelas relacionais. A biblioteca do Spark SQL que fornece o objeto de dataframe também dá suporte ao uso de instruções SQL para consultar as tabelas no metastore. Usando essas funcionalidades do Spark, você pode combinar a flexibilidade de um data lake com o esquema de dados estruturado e as consultas baseadas em SQL de um data warehouse relacional, daí o termo "data lakehouse". +Como você viu, os métodos nativos do objeto DataFrame permitem que você consulte e analise os dados a partir de um arquivo. No entanto, você pode se sentir mais confortável trabalhando com tabelas usando a sintaxe SQL. O Spark fornece um metastore no qual você pode definir tabelas relacionais. + +A biblioteca do Spark SQL permite o uso de instruções SQL para consultar tabelas no metastore. Isso dá a flexibilidade de um data lake com o esquema de dados estruturado e as consultas baseadas em SQL de um data warehouse relacional, daí o termo "data lakehouse". ### Criar uma tabela -As tabelas em um metastore do Spark são abstrações relacionais em arquivos no data lake. As tabelas podem ser *gerenciadas* (nesse caso, os arquivos são gerenciados pelo metastore) ou *externas* (nesse caso, a tabela referencia um local de arquivo no data lake que você gerencia independentemente do metastore). +As tabelas em um metastore do Spark são abstrações relacionais em arquivos no data lake. As tabelas podem ser *gerenciadas* pelo metastore ou *externas* e gerenciadas de forma independente do metastore. -1. Adicione uma nova célula de código ao notebook e insira o seguinte código, que salva o dataframe dos dados do pedido de vendas como uma tabela chamada **salesorders**: +1. Adicione uma célula de código ao notebook e insira o seguinte código, que salva o DataFrame dos dados do pedido de vendas como uma tabela chamada *salesorders*: - ```Python - # Create a new table - df.write.format("delta").saveAsTable("salesorders") +```python +# Create a new table +df.write.format("delta").saveAsTable("salesorders") - # Get the table description - spark.sql("DESCRIBE EXTENDED salesorders").show(truncate=False) - ``` +# Get the table description +spark.sql("DESCRIBE EXTENDED salesorders").show(truncate=False) +``` - > **Observação**: vale a pena observar algumas coisas sobre este exemplo. Em primeiro lugar, nenhum caminho explícito é fornecido, ou seja, os arquivos da tabela serão gerenciados pelo metastore. Em segundo lugar, a tabela é salva no formato **delta**. Você pode criar tabelas com base em vários formatos de arquivo (incluindo CSV, Parquet, Avro e outros), mas o *Delta Lake* é uma tecnologia do Spark que adiciona funcionalidades de banco de dados relacional a tabelas; incluindo suporte para transações, controle de versão de linha e outros recursos úteis. A criação de tabelas no formato delta é preferencial para data lakehouses no Fabric. +>[!NOTE] +> Neste exemplo, nenhum caminho explícito é fornecido; portanto, os arquivos da tabela serão gerenciados pelo metastore. Além disso, a tabela é salva no formato delta, que adiciona recursos de banco de dados relacional às tabelas. Isso inclui suporte para transações, controle de versão de linha e outros recursos úteis. A criação de tabelas no formato delta é preferencial para data lakehouses no Fabric. 2. Execute a célula de código e analise a saída, que descreve a definição da nova tabela. -3. No painel **Lakehouses**, no menu **…** da pasta **Tabelas**, selecione **Atualizar**. Em seguida, expanda o nó **Tabelas** e verifique se a tabela **salesorders** foi criada. +3. No painel **Lakehouses**, no menu ... da pasta Tabelas, clique em **Atualizar**. Em seguida, expanda o nó **Tabelas** e verifique se a tabela **salesorders** foi criada. - ![Captura de tela da tabela salesorder no Explorer.](./Images/table-view.png) +![Imagem da tela mostrando que a tabela salesorders foi criada.](Images/salesorders-table.jpg) -5. No menu **…** da tabela **salesorders**, selecione **Carregar dados** > **Spark**. +4. No menu … da tabela salesorders, clique em **Carregar dados** > **Spark**. Uma nova célula de código que contém um código semelhante ao seguinte exemplo é adicionada: - Uma nova célula de código que contém um código semelhante ao seguinte exemplo é adicionada ao notebook: +```pyspark +df = spark.sql("SELECT * FROM [your_lakehouse].salesorders LIMIT 1000") - ```Python - df = spark.sql("SELECT * FROM [your_lakehouse].salesorders LIMIT 1000") - display(df) - ``` +display(df) +``` -6. Execute o novo código, que usa a biblioteca do Spark SQL para inserir uma consulta SQL na tabela **salesorder** no código PySpark e carregar os resultados da consulta em um dataframe. +5. Execute o novo código, que usa a biblioteca do Spark SQL para inserir uma consulta SQL na tabela *salesorder* no código PySpark e carregar os resultados da consulta em um DataFrame. ### Executar um código SQL em uma célula -Embora seja útil a inserção de instruções SQL em uma célula que contém um código PySpark, os analistas de dados costumam desejar apenas trabalhar diretamente no SQL. +Embora seja útil a inserção de instruções SQL em uma célula que contém código PySpark, os analistas de dados muitas vezes preferem trabalhar diretamente com SQL. -1. Adicione uma nova célula de código ao notebook e insira o seguinte código nela: +1. Adicione uma nova célula de código ao notebook e insira o seguinte código: - ```sql - %%sql - SELECT YEAR(OrderDate) AS OrderYear, - SUM((UnitPrice * Quantity) + Tax) AS GrossRevenue - FROM salesorders - GROUP BY YEAR(OrderDate) - ORDER BY OrderYear; - ``` - -2. Execute a célula e analise os resultados. Observe que: - - A linha `%%sql` no início da célula (chamada *magic*) indica que o runtime da linguagem Spark SQL deve ser usado para executar o código nessa célula em vez do PySpark. - - O código SQL referencia a tabela **salesorders** que você já criou. - - A saída da consulta SQL é exibida automaticamente como o resultado abaixo da célula. +```SparkSQL +%%sql +SELECT YEAR(OrderDate) AS OrderYear, + SUM((UnitPrice * Quantity) + Tax) AS GrossRevenue +FROM salesorders +GROUP BY YEAR(OrderDate) +ORDER BY OrderYear; +``` + +7. Execute a célula e analise os resultados. Observe que: + +* O comando **%%sql** no início da célula (chamado de magic) altera a linguagem para Spark SQL em vez de PySpark. +* O código SQL referencia a tabela *salesorders* que você já criou. +* A saída da consulta SQL é exibida automaticamente como o resultado abaixo da célula. -> **Observação**: para obter mais informações sobre o Spark SQL e os dataframes, confira a [documentação do Spark SQL](https://spark.apache.org/docs/2.2.0/sql-programming-guide.html). +>[!NOTE] +> Para mais informações sobre o Spark SQL e os dataframes, confira a documentação do [Apache Spark SQL](https://spark.apache.org/sql/). ## Visualizar os dados com o Spark -Como o provérbio diz, uma imagem vale mil palavras, e um gráfico geralmente é melhor do que mil linhas de dados. Embora os notebooks do Fabric incluam uma exibição de gráfico interna para dados exibidos em um dataframe ou em uma consulta Spark SQL, ele não foi projetado para gráficos abrangentes. No entanto, você pode usar bibliotecas de elementos gráficos do Python, como a **matplotlib** e a **seaborn**, para criar gráficos com base em dados em dataframes. +Os gráficos ajudam você a ver padrões e tendências com mais rapidez do que seria possível verificando milhares de linhas de dados. Os notebooks do Fabric incluem uma exibição de gráfico integrada, mas não foram projetados para gráficos complexos. Para obter mais controle sobre como os gráficos são criados a partir de dados em DataFrames, use bibliotecas gráficas em Python como *matplotlib* ou *seaborn*. ### Exibir os resultados como um gráfico -1. Adicione uma nova célula de código ao notebook e insira o seguinte código nela: +1. Adicione uma nova célula de código e insira o seguinte código: - ```sql - %%sql - SELECT * FROM salesorders - ``` +```python +%%sql +SELECT * FROM salesorders +``` -2. Execute o código e observe que ele retorna os dados da exibição **salesorders** que você já criou. -3. Na seção de resultados abaixo da célula, altere a opção **Exibir** de **Tabela** para **Gráfico**. -4. Use o botão **Personalizar gráfico** no canto superior direito do gráfico para exibir o painel de opções do gráfico. Em seguida, defina as opções da seguinte maneira e selecione **Aplicar**: - - **Tipo de gráfico**: Gráfico de barras - - **Chave**: Item - - **Valores**: Quantidade - - **Grupo de Séries**: *deixe em branco* - - **Agregação**: Soma - - **Empilhado**: *Não selecionado* +2. Execute o código para exibir dados da exibição salesorders que você criou anteriormente. Na seção de resultados abaixo da célula, altere a opção **Exibir** de **Tabela** para **Gráfico**. -5. Verifique se o gráfico é parecido com este: +3. Use o botão **Personalizar gráfico** no canto superior direito do gráfico para definir as seguintes opções: - ![Captura de tela de um gráfico de barras de produtos pela quantidade total de pedidos](./Images/notebook-chart.png) +* Tipo de gráfico: Gráfico de barras +* Chave: Item +* Valores: Quantidade +* Grupo de Séries: deixe em branco +* Agregação: Soma +* Empilhado: Não selecionado -### Introdução à **matplotlib** +Ao terminar, clique em **Aplicar**. -1. Adicione uma nova célula de código ao notebook e insira o seguinte código nela: +4. Seu gráfico será semelhante a este: - ```Python - sqlQuery = "SELECT CAST(YEAR(OrderDate) AS CHAR(4)) AS OrderYear, \ - SUM((UnitPrice * Quantity) + Tax) AS GrossRevenue \ - FROM salesorders \ - GROUP BY CAST(YEAR(OrderDate) AS CHAR(4)) \ - ORDER BY OrderYear" - df_spark = spark.sql(sqlQuery) - df_spark.show() - ``` +![Imagem da tela da visualização do gráfico do notebook do Fabric.](Images/built-in-chart.jpg) -2. Execute o código e observe se ele retorna um dataframe do Spark que contém a receita anual. +### Introdução à matplotlib - Para visualizar os dados como um gráfico, começaremos usando a biblioteca **matplotlib** do Python. Essa biblioteca é a biblioteca de plotagem principal na qual muitas outras se baseiam e fornece muita flexibilidade na criação de gráficos. +1. Adicione uma nova célula de código e insira o seguinte código: -3. Adicione uma nova célula de código ao notebook e adicione o seguinte código a ele: +```python +sqlQuery = "SELECT CAST(YEAR(OrderDate) AS CHAR(4)) AS OrderYear, \ + SUM((UnitPrice * Quantity) + Tax) AS GrossRevenue \ + FROM salesorders \ + GROUP BY CAST(YEAR(OrderDate) AS CHAR(4)) \ + ORDER BY OrderYear" +df_spark = spark.sql(sqlQuery) +df_spark.show() +``` - ```Python - from matplotlib import pyplot as plt +2. Execute o código. Retornará um DataFrame do Spark contendo a receita anual. Para visualizar os dados como um gráfico, começaremos usando a biblioteca matplotlib em Python. Essa biblioteca é a biblioteca de plotagem principal na qual muitas outras se baseiam e fornece muita flexibilidade na criação de gráficos. - # matplotlib requires a Pandas dataframe, not a Spark one - df_sales = df_spark.toPandas() +3. Adicione uma nova célula de código e o seguinte código: - # Create a bar plot of revenue by year - plt.bar(x=df_sales['OrderYear'], height=df_sales['GrossRevenue']) +```python +from matplotlib import pyplot as plt - # Display the plot - plt.show() - ``` +# matplotlib requires a Pandas dataframe, not a Spark one +df_sales = df_spark.toPandas() -4. Execute a célula e analise os resultados, que consistem em um gráfico de colunas com a receita bruta total de cada ano. Observe os seguintes recursos do código usado para produzir este gráfico: - - A biblioteca **matplotlib** exige um dataframe do *Pandas*, ou seja, você precisa converter o dataframe do *Spark* retornado pela consulta Spark SQL nesse formato. - - No núcleo da biblioteca **matplotlib** está o objeto **pyplot**. Essa é a base para a maioria das funcionalidades de plotagem. - - As configurações padrão resultam em um gráfico utilizável, mas há um escopo considerável para personalizá-lo +# Create a bar plot of revenue by year +plt.bar(x=df_sales['OrderYear'], height=df_sales['GrossRevenue']) -5. Modifique o código para plotar o gráfico da seguinte maneira: +# Display the plot +plt.show() +``` - ```Python - from matplotlib import pyplot as plt +4. Execute a célula e analise os resultados, que consistem em um gráfico de colunas com a receita bruta total de cada ano. Examine o código e observe o seguinte: - # Clear the plot area - plt.clf() +* A biblioteca matplotlib requer um DataFrame do Pandas; portanto, você precisa converter o DataFrame do Spark retornado pela consulta Spark SQL. +* No núcleo da biblioteca matplotlib está o objeto *pyplot*. Essa é a base para a maioria das funcionalidades de plotagem. +* As configurações padrão resultam em um gráfico utilizável, mas há muitas possibilidades de personalização. - # Create a bar plot of revenue by year - plt.bar(x=df_sales['OrderYear'], height=df_sales['GrossRevenue'], color='orange') +5. Modifique o código para plotar o gráfico da seguinte maneira: - # Customize the chart - plt.title('Revenue by Year') - plt.xlabel('Year') - plt.ylabel('Revenue') - plt.grid(color='#95a5a6', linestyle='--', linewidth=2, axis='y', alpha=0.7) - plt.xticks(rotation=45) +```python +from matplotlib import pyplot as plt - # Show the figure - plt.show() - ``` +# Clear the plot area +plt.clf() -6. Execute novamente a célula de código e veja os resultados. O gráfico agora inclui um pouco mais de informações. +# Create a bar plot of revenue by year +plt.bar(x=df_sales['OrderYear'], height=df_sales['GrossRevenue'], color='orange') - Tecnicamente, um gráfico está contido com uma **Figura**. Nos exemplos anteriores, a figura foi criada implicitamente, mas você pode criá-la de modo explícito. +# Customize the chart +plt.title('Revenue by Year') +plt.xlabel('Year') +plt.ylabel('Revenue') +plt.grid(color='#95a5a6', linestyle='--', linewidth=2, axis='y', alpha=0.7) +plt.xticks(rotation=45) -7. Modifique o código para plotar o gráfico da seguinte maneira: +# Show the figure +plt.show() +``` - ```Python - from matplotlib import pyplot as plt +6. Execute novamente a célula de código e veja os resultados. Agora está mais fácil de entender o gráfico. +7. Um gráfico está contido com uma Figura. Nos exemplos anteriores, a figura foi criada implicitamente, mas pode ser criada explicitamente. Modifique o código para plotar o gráfico da seguinte maneira: - # Clear the plot area - plt.clf() +```python +from matplotlib import pyplot as plt - # Create a Figure - fig = plt.figure(figsize=(8,3)) +# Clear the plot area +plt.clf() - # Create a bar plot of revenue by year - plt.bar(x=df_sales['OrderYear'], height=df_sales['GrossRevenue'], color='orange') +# Create a Figure +fig = plt.figure(figsize=(8,3)) - # Customize the chart - plt.title('Revenue by Year') - plt.xlabel('Year') - plt.ylabel('Revenue') - plt.grid(color='#95a5a6', linestyle='--', linewidth=2, axis='y', alpha=0.7) - plt.xticks(rotation=45) +# Create a bar plot of revenue by year +plt.bar(x=df_sales['OrderYear'], height=df_sales['GrossRevenue'], color='orange') - # Show the figure - plt.show() - ``` +# Customize the chart +plt.title('Revenue by Year') +plt.xlabel('Year') +plt.ylabel('Revenue') +plt.grid(color='#95a5a6', linestyle='--', linewidth=2, axis='y', alpha=0.7) +plt.xticks(rotation=45) -8. Execute novamente a célula de código e veja os resultados. A figura determina a forma e o tamanho do gráfico. +# Show the figure +plt.show() +``` - Uma figura pode conter vários subgráficos, cada um em um *eixo* próprio. +8. Execute novamente a célula de código e veja os resultados. A figura determina a forma e o tamanho do gráfico. +9. Uma figura pode conter vários subgráficos, cada um em um eixo próprio. Modifique o código para plotar o gráfico da seguinte maneira: -9. Modifique o código para plotar o gráfico da seguinte maneira: +```python +from matplotlib import pyplot as plt - ```Python - from matplotlib import pyplot as plt +# Clear the plot area +plt.clf() - # Clear the plot area - plt.clf() +# Create a figure for 2 subplots (1 row, 2 columns) +fig, ax = plt.subplots(1, 2, figsize = (10,4)) - # Create a figure for 2 subplots (1 row, 2 columns) - fig, ax = plt.subplots(1, 2, figsize = (10,4)) +# Create a bar plot of revenue by year on the first axis +ax[0].bar(x=df_sales['OrderYear'], height=df_sales['GrossRevenue'], color='orange') +ax[0].set_title('Revenue by Year') - # Create a bar plot of revenue by year on the first axis - ax[0].bar(x=df_sales['OrderYear'], height=df_sales['GrossRevenue'], color='orange') - ax[0].set_title('Revenue by Year') +# Create a pie chart of yearly order counts on the second axis +yearly_counts = df_sales['OrderYear'].value_counts() +ax[1].pie(yearly_counts) +ax[1].set_title('Orders per Year') +ax[1].legend(yearly_counts.keys().tolist()) - # Create a pie chart of yearly order counts on the second axis - yearly_counts = df_sales['OrderYear'].value_counts() - ax[1].pie(yearly_counts) - ax[1].set_title('Orders per Year') - ax[1].legend(yearly_counts.keys().tolist()) +# Add a title to the Figure +fig.suptitle('Sales Data') - # Add a title to the Figure - fig.suptitle('Sales Data') +# Show the figure +plt.show() +``` - # Show the figure - plt.show() - ``` +10. Execute novamente a célula de código e veja os resultados. -10. Execute novamente a célula de código e veja os resultados. A figura contém os subgráficos especificados no código. +>[!NOTE] +> Para saber mais sobre plotagem com a matplotlib, confira a documentação da [matplotlib](https://matplotlib.org/). -> **Observação**: para saber mais sobre a plotagem com a matplotlib, confira a [documentação da matplotlib](https://matplotlib.org/). +### Usar a biblioteca seaborn -### Usar a biblioteca **seaborn** +Embora a *matplotlib* permita que você crie diferentes tipos de gráfico, a biblioteca pode precisar de código complexo para obter os melhores resultados. Por esse motivo, novas bibliotecas foram criadas com base na matplotlib para abstrair a complexidade e aprimorar as funcionalidades. Uma dessas bibliotecas é a seaborn. -Embora a **matplotlib** permita que você crie gráficos complexos de vários tipos, ele pode exigir um código complexo para obter os melhores resultados. Por esse motivo, ao longo dos anos, muitas bibliotecas foram criadas na base na matplotlib para abstrair a complexidade e aprimorar as funcionalidades. Uma dessas bibliotecas é a **seaborn**. +1. Adicione uma nova célula de código ao notebook e insira o seguinte código: -1. Adicione uma nova célula de código ao notebook e insira o seguinte código nela: +```python +import seaborn as sns - ```Python - import seaborn as sns +# Clear the plot area +plt.clf() - # Clear the plot area - plt.clf() +# Create a bar chart +ax = sns.barplot(x="OrderYear", y="GrossRevenue", data=df_sales) - # Create a bar chart - ax = sns.barplot(x="OrderYear", y="GrossRevenue", data=df_sales) - plt.show() - ``` +plt.show() +``` -2. Execute o código e observe que ele exibe um gráfico de barras usando a biblioteca seaborn. +2. Execute o código para exibir um gráfico de barras usando a biblioteca seaborn. 3. Modifique o código da seguinte maneira: - ```Python - import seaborn as sns - - # Clear the plot area - plt.clf() +```python +import seaborn as sns - # Set the visual theme for seaborn - sns.set_theme(style="whitegrid") +# Clear the plot area +plt.clf() - # Create a bar chart - ax = sns.barplot(x="OrderYear", y="GrossRevenue", data=df_sales) - plt.show() - ``` +# Set the visual theme for seaborn +sns.set_theme(style="whitegrid") -4. Execute o código modificado e observe que a seaborn permite que você defina um tema de cor consistente para seus gráficos. +# Create a bar chart +ax = sns.barplot(x="OrderYear", y="GrossRevenue", data=df_sales) -5. Modifique o código novamente da seguinte maneira: +plt.show() +``` - ```Python - import seaborn as sns +4. Execute o código modificado e observe que a seaborn permite que você defina um tema de cor para os gráficos. +5. Modifique o código novamente da seguinte maneira: - # Clear the plot area - plt.clf() +```python +import seaborn as sns - # Create a line chart - ax = sns.lineplot(x="OrderYear", y="GrossRevenue", data=df_sales) - plt.show() - ``` +# Clear the plot area +plt.clf() -6. Execute o código modificado para ver a receita anual como um gráfico de linhas. +# Create a line chart +ax = sns.lineplot(x="OrderYear", y="GrossRevenue", data=df_sales) -> **Observação**: para saber mais sobre como fazer uma plotagem com a seaborn, confira a [documentação da seaborn](https://seaborn.pydata.org/index.html). +plt.show() +``` -## Salvar o notebook e encerrar a sessão do Spark +6. Execute o código modificado para ver a receita anual como um gráfico de linhas. -Agora que terminou de trabalhar com os dados, salve o notebook com um nome significativo e encerre a sessão do Spark. - -1. Na barra de menus do notebook, use o ícone ⚙️ de **Configurações** para ver as configurações do notebook. -2. Defina o **Nome** do notebook como **Explorar Pedidos de Vendas** e feche o painel de configurações. -3. No menu do notebook, selecione **Parar sessão** para encerrar a sessão do Spark. +>[!NOTE] +> Para saber mais sobre plotagem com a seaborn, confira a documentação da [seaborn](https://seaborn.pydata.org/index.html). ## Limpar os recursos -Neste exercício, você aprendeu a usar o Spark para trabalhar com os dados no Microsoft Fabric. +Neste exercício, você aprendeu a usar o Spark para trabalhar com dados no Microsoft Fabric. + +Se você tiver terminado de explorar seus dados, encerre a sessão do Spark e exclua o espaço de trabalho criado para este exercício. -Se você tiver terminado de explorar seu lakehouse, exclua o workspace criado para este exercício. +1. No menu do notebook, selecione **Parar sessão** para encerrar a sessão do Spark. +1. Na barra à esquerda, selecione o ícone do workspace para ver todos os itens que ele contém. +1. Clique em **Configurações do espaço de trabalho** e, na seção **Geral**, role para baixo e selecione **Remover este espaço de trabalho**. +1. Clique em **Excluir** para excluir o espaço de trabalho. -1. Na barra à esquerda, selecione o ícone do workspace para ver todos os itens que ele contém. -2. No menu **…** da barra de ferramentas, selecione **Configurações do workspace**. -3. Na seção **Geral**, selecione **Remover este espaço de trabalho**. diff --git a/Instructions/Labs/03-delta-lake.md b/Instructions/Labs/03-delta-lake.md index a885ab1..4867c8a 100644 --- a/Instructions/Labs/03-delta-lake.md +++ b/Instructions/Labs/03-delta-lake.md @@ -6,322 +6,369 @@ lab: # Usar tabelas Delta no Apache Spark -As tabelas de um lakehouse do Microsoft Fabric são baseadas no formato *Delta Lake* de código aberto para o Apache Spark. O Delta Lake adiciona suporte para a semântica relacional em operações de dados em lote e streaming e permite a criação de uma arquitetura de Lakehouse na qual o Apache Spark pode ser usado para processar e consultar dados em tabelas baseadas em arquivos subjacentes em um data lake. +As tabelas de um lakehouse do Microsoft Fabric são baseadas no formato Delta Lake de código aberto. O Delta Lake adiciona suporte para semântica relacional para dados em lote e de streaming. Neste exercício, você criará tabelas Delta e explorará os dados usando consultas SQL. -Este exercício levará aproximadamente **40** minutos para ser concluído +Este exercício deve levar aproximadamente 45 minutos para ser concluído -> **Observação**: Você precisará de uma [avaliação do Microsoft Fabric](https://learn.microsoft.com/fabric/get-started/fabric-trial) para concluir esse exercício. +> [!NOTE] +> Você precisa de uma avaliação do [Microsoft Fabric](/fabric/get-started/fabric-trial) para concluir esse exercício. ## Criar um workspace -Antes de trabalhar com os dados no Fabric, crie um workspace com a avaliação do Fabric habilitada. +Primeiro, crie um espaço de trabalho com a *avaliação do Fabric* habilitada. -1. Na [página inicial do Microsoft Fabric](https://app.fabric.microsoft.com/home?experience=fabric) no `https://app.fabric.microsoft.com/home?experience=fabric`, selecione **Engenharia de Dados do Synapse**. -2. Na barra de menus à esquerda, selecione **Workspaces** (o ícone é semelhante a 🗇). -3. Crie um workspace com um nome de sua escolha selecionando um modo de licenciamento que inclua a capacidade do Fabric (*Avaliação*, *Premium* ou *Malha*). -4. Quando o novo workspace for aberto, ele estará vazio. +1. Na home page do Microsoft Fabric em https://app.fabric.microsoft.com, escolha a experiência **Engenharia de Dados do Synapse**. +1. Na barra de menus à esquerda, selecione **Espaços de Trabalho** (🗇). +1. Crie um **novo espaço de trabalho** com um nome de sua escolha selecionando um modo de licenciamento que inclua a capacidade do Fabric (Avaliação, Premium ou Fabric). +1. Quando o novo workspace for aberto, ele estará vazio. - ![Captura de tela de um espaço de trabalho vazio no Fabric.](./Images/new-workspace.png) +![Imagem da tela de um espaço de trabalho vazio do Fabric.](Images/workspace-empty.jpg) ## Criar um lakehouse e carregar dados -Agora que você tem um espaço de trabalho, é hora de criar um data lakehouse para os dados que serão analisados. +Agora que você tem um espaço de trabalho, é hora de criar um lakehouse e carregar alguns dados. -1. Na home page da **Engenharia de Dados do Synapse**, crie um **Lakehouse** com um nome de sua escolha. +1. Na home page da **Engenharia de Dados do Synapse**, crie um **Lakehouse** com um nome de sua escolha. +1. Há várias maneiras de ingerir dados, mas neste exercício, você baixará um arquivo de texto no computador local (ou na VM de laboratório, se aplicável) e fará seu upload no lakehouse. Baixe o [arquivo de dados](https://github.com/MicrosoftLearning/dp-data/raw/main/products.csv) em https://github.com/MicrosoftLearning/dp-data/raw/main/products.csv, salvando-o como *products.csv*. +1. Retorne à guia do navegador da Web que contém seu lakehouse e, no painel do Explorer, ao lado da pasta **Arquivos**, clique no menu. Crie uma **Nova subpasta** chamada *products*. +1. No menu ... da pasta products, **carregue** o arquivo *products.csv* do computador local (ou da VM do laboratório, se aplicável). +1. Depois que o arquivo for carregado, selecione a pasta **products** e verifique se o arquivo foi carregado, conforme mostrado aqui: - Após alguns minutos, um lakehouse vazio. Você precisa ingerir alguns dados no data lakehouse para análise. Há várias maneiras de fazer isso, mas neste exercício, você apenas baixará um arquivo de texto no computador local (ou na VM de laboratório, se aplicável) e o carregará no lakehouse. +![Imagem de tela de products.csv carregado no lakehouse.](Images/upload-products.jpg) + +## Explorar dados em um DataFrame -1. Baixe o [arquivo de dados](https://github.com/MicrosoftLearning/dp-data/raw/main/products.csv) para este exercício em `https://github.com/MicrosoftLearning/dp-data/raw/main/products.csv` e salve-o como **products.csv** no computador local (ou na VM de laboratório, se aplicável). +1. Crie um **Novo notebook**. Após alguns segundos, um novo notebook que contém uma só célula será aberto. Os notebooks são compostos por uma ou mais células que podem conter um código ou um markdown (texto formatado). +2. Selecione a primeira célula (que atualmente é uma célula de código) e, na barra de ferramentas no canto superior direito, use o botão **M↓** para convertê-la em uma célula Markdown. O texto contido na célula será então exibido como texto formatado. Use células Markdown para fornecer informações explicativas sobre seu código. +3. Use o botão 🖉 (Editar) para alternar a célula para o modo de edição e modifique o Markdown desta maneira: -1. Volte à guia do navegador da Web que contém o lakehouse e, no menu **…** da pasta **Arquivos** no painel do **Explorer**, selecione **Nova subpasta** e crie uma pasta chamada **products**. +```markdown +# Delta Lake tables +Use this notebook to explore Delta Lake functionality +``` -1. No menu **…** da pasta **products**, selecione **Carregar** e **Carregar arquivos** e carregue o arquivo **products.csv** do computador local (ou da VM de laboratório, se aplicável) para o lakehouse. -1. Depois que o arquivo for carregado, selecione a pasta **products** e verifique se o arquivo **products.csv** foi carregado, conforme mostrado aqui: +4. Clique em qualquer lugar no notebook fora da célula para parar de editá-lo e ver o markdown renderizado. +5. Adicione uma nova célula de código e o seguinte código para ler os dados de produtos em um DataFrame usando um esquema definido: - ![Captura de tela do arquivo products.csv carregado em um lakehouse.](./Images/products-file.png) +```python +from pyspark.sql.types import StructType, IntegerType, StringType, DoubleType -## Explorar os dados em um dataframe +# define the schema +schema = StructType() \ +.add("ProductID", IntegerType(), True) \ +.add("ProductName", StringType(), True) \ +.add("Category", StringType(), True) \ +.add("ListPrice", DoubleType(), True) -1. Na **Home page**, ao exibir o conteúdo da pasta **products** no data lake, no menu **Abrir notebook**, selecione **Novo notebook**. +df = spark.read.format("csv").option("header","true").schema(schema).load("Files/products/products.csv") +# df now is a Spark DataFrame containing CSV data from "Files/products/products.csv". +display(df) +``` - Após alguns segundos, um novo notebook que contém uma só *célula* será aberto. Os notebooks são compostos por uma ou mais células que podem conter um *código* ou um *markdown* (texto formatado). +> [!TIP] +> Oculte ou exiba os painéis do explorador usando o ícone de divisa «. Isso permite que você se concentre no notebook ou em seus arquivos. -2. Selecione a célula existente no notebook, que contém um código simples e use o ícone **🗑** (*Excluir*) dele no canto superior direito para removê-lo. Você não precisará desse código. -3. No painel do **Explorer**, expanda **Lakehouses** e, em seguida, expanda a lista de **Arquivos** do seu lakehouse e selecione a pasta **produtos** para revelar um novo painel mostrando o arquivo **products.csv** que você já carregou: +7. Use o botão **Executar célula** (▷) à esquerda da célula para executá-la. - ![Captura de tela de um notebook com um painel Arquivos.](./Images/notebook-products.png) +> [!NOTE] +> Como esta é a primeira vez que você executa qualquer código Spark neste notebook, uma sessão do Spark precisa ser iniciada. Isso significa que a primeira execução pode levar alguns minutos para ser concluída. As execuções seguintes serão mais rápidas. -4. No menu **…** de **products.csv**, selecione **Carregar dados** > **Spark**. Uma nova célula de código que contém o seguinte código deve ser adicionada ao notebook: +8. Quando o código da célula for concluído, analise a saída abaixo da célula, que será semelhante a esta: - ```python - df = spark.read.format("csv").option("header","true").load("Files/products/products.csv") - # df now is a Spark DataFrame containing CSV data from "Files/products/products.csv". - display(df) - ``` +![Imagem de tela dos dados de products.csv.](Images/products-schema.jpg) + +## Criar tabelas Delta - > **Dica**: oculte o painel que contém os arquivos à esquerda usando o ícone **<<** . Isso ajudará você a se concentrar no notebook. +Você pode salvar o DataFrame como uma tabela Delta usando o método *saveAsTable*. O Delta Lake dá suporte à criação de tabelas gerenciadas e externas. -5. Use o botão **▷** (*Executar célula*) à esquerda da célula para executá-la. +* As tabelas Delta **gerenciadas** se beneficiam de um desempenho mais alto, uma vez que o Fabric gerencia os metadados do esquema e os arquivos de dados. +* As tabelas **externas** permitem que você armazene dados externamente, com os metadados gerenciados pelo Fabric. - > **Observação**: como esta é a primeira vez que você executa qualquer código Spark neste notebook, uma sessão do Spark precisa ser iniciada. Isso significa que a primeira execução pode levar alguns minutos para ser concluída. As execuções seguintes serão mais rápidas. +### Criar uma tabela gerenciada -6. Quando o comando de célula for concluído, analise a saída abaixo da célula, que deve ser semelhante a essa: +Os arquivos de dados são criados na pasta **Tabelas**. - | Índice | ProductID | ProductName | Categoria | ListPrice | - | -- | -- | -- | -- | -- | - | 1 | 771 | Mountain-100 Silver, 38 | Mountain bikes | 3399.9900 | - | 2 | 772 | Mountain-100 Silver, 42 | Mountain bikes | 3399.9900 | - | 3 | 773 | Mountain-100 Silver, 44 | Mountain bikes | 3399.9900 | - | ... | ... | ... | ... | ... | +1. Nos resultados retornados pela primeira célula de código, use o ícone + Código para adicionar uma nova célula de código. -## Criar tabelas Delta +> [!TIP] +> Para ver o ícone + Código, posicione o mouse um pouco abaixo e à esquerda da saída da célula atual. Como alternativa, na barra de menus, na guia Editar, clique em **+ Adicionar célula de código**. -Você pode salvar o dataframe como uma tabela delta usando o método `saveAsTable`. O Delta Lake dá suporte à criação de tabelas *gerenciadas* e *externas*. +2. Para criar uma tabela Delta gerenciada, adicione uma célula, insira o código a seguir e execute a célula: -### Criar uma tabela *gerenciada* +```python +df.write.format("delta").saveAsTable("managed_products") +``` -Tabelas *gerenciadas* são tabelas para as quais os metadados de esquema e os arquivos de dados são gerenciados pelo Fabric. Os arquivos de dados da tabela são criados na pasta **Tabelas**. +3. No painel do Lakehouse Explorer, **atualize** a pasta Tabelas e expanda o nó Tabelas para verificar se a tabela **managed_products** foi criada. -1. Nos resultados retornados pela primeira célula de código, use o ícone **+ Código** para adicionar uma nova célula de código caso ainda não exista uma. +>[!NOTE] +> O ícone de triângulo ao lado do nome do arquivo indica uma tabela Delta. - > **Dica**: Para ver o ícone **+ Código**, posicione o mouse um pouco abaixo e à esquerda da saída da célula atual. Como alternativa, na barra de menus, na guia **Editar**, selecione **+ Adicionar célula de código**. +Os arquivos da tabela gerenciada são armazenados na pasta **Tabelas** no lakehouse. Uma pasta chamada *managed_products* foi criada e armazena os arquivos Parquet e a pasta delta_log da tabela. -2. Insira o seguinte código na nova célula e execute-o: +### Criar uma tabela externa - ```python - df.write.format("delta").saveAsTable("managed_products") - ``` +Você também pode criar tabelas externas, que podem ser armazenadas em outro lugar que não o lakehouse, com os metadados do esquema armazenados no lakehouse. -3. No painel do **Lakehouse Explorer**, no menu **…** da pasta **Tabelas**, selecione **Atualizar**. Em seguida, expanda o nó **Tabelas** e verifique se a tabela **managed_products** foi criada. +1. No painel do Lakehouse Explorer, no menu ... da pasta **Arquivos**, clique em **Copiar caminho do ABFS**. O caminho do ABFS é o caminho totalmente qualificado para a pasta Arquivos do lakehouse. -### Criar uma tabela *externa* +2. Em uma nova célula de código, cole o caminho do ABFS. Adicione o seguinte código, usando recortar e colar para inserir o abfs_path no local correto no código: -Crie também tabelas *externas* para as quais os metadados de esquema são definidos no metastore para o lakehouse, mas os arquivos de dados são armazenados em um local externo. +```python +df.write.format("delta").saveAsTable("external_products", path="abfs_path/external_products") +``` -1. Adicione outra nova célula de código e adicione o seguinte código a ela: +O caminho completo será parecido com este: - ```python - df.write.format("delta").saveAsTable("external_products", path="abfs_path/external_products") - ``` +```python +abfss://workspace@tenant-onelake.dfs.fabric.microsoft.com/lakehousename.Lakehouse/Files/external_products +``` -2. No painel do **Lakehouse Explorer**, no menu **…** da pasta **Arquivos**, selecione **Copiar caminho do ABFS**. +4. **Execute** a célula para salvar o DataFrame como uma tabela externa na pasta Files/external_products. - O caminho do ABFS é o caminho totalmente qualificado para a pasta **Arquivos** no armazenamento OneLake do lakehouse, semelhante a este: +5. No painel do Lakehouse Explorer, **atualize** a pasta Tabelas, expanda o nó Tabelas e verifique se a tabela external_products foi criada contendo os metadados do esquema. - *abfss://workspace@tenant-onelake.dfs.fabric.microsoft.com/lakehousename.Lakehouse/Files* +6. No painel do Lakehouse Explorer, no menu ... da pasta Arquivos, clique em **Atualizar**. Em seguida, expanda o nó Arquivos e verifique se a pasta external_products foi criada para os arquivos de dados da tabela. -3. No código que você inseriu na célula de código, substitua **abfs_path** pelo caminho que você copiou para a área de transferência para que o código salve o dataframe como uma tabela externa com arquivos de dados em uma pasta chamada **external_products** no local da pasta **Files**. O caminho completo será parecido com este: +### Comparar tabelas gerenciadas e externas - *abfss://workspace@tenant-onelake.dfs.fabric.microsoft.com/lakehousename.Lakehouse/Files/external_products* +Vamos explorar as diferenças entre as tabelas gerenciadas e externas usando o comando magic %%sql. -4. No painel do **Lakehouse Explorer**, no menu **…** da pasta **Tabelas**, selecione **Atualizar**. Em seguida, expanda o nó **Tabelas** e verifique se a tabela **external_products** foi criada. +1. Em uma nova célula de código, adicione e execute o seguinte código: -5. No painel do **Lakehouse Explorer**, no menu **…** da pasta **Arquivos**, selecione **Atualizar**. Em seguida, expanda o nó **Arquivos** e verifique se a pasta **external_products** foi criada para os arquivos de dados da tabela. +```pthon +%%sql +DESCRIBE FORMATTED managed_products; +``` -### Comparar tabelas *gerenciadas* e *externas* +2. Nos resultados, exiba a propriedade Local da tabela. Clique no valor Local na coluna Tipo de dados para ver o caminho completo. Observe que o local de armazenamento do OneLake termina com /Tables/managed_products. -Vamos explorar as diferenças entre as tabelas gerenciadas e externas. +3. Modifique o comando DESCRIBE para exibir os detalhes da tabela external_products conforme mostrado aqui: -1. Adicione outra célula de código e execute o seguinte código: +```python +%%sql +DESCRIBE FORMATTED external_products; +``` + +4. Execute a célula e, nos resultados, exiba a propriedade Local da tabela. Amplie a coluna Tipo de dados para ver o caminho completo e observe que os locais de armazenamento do OneLake terminam com /Files/external_products. - ```sql - %%sql +5. Em uma nova célula de código, adicione e execute o seguinte código: - DESCRIBE FORMATTED managed_products; - ``` +```python +%%sql +DROP TABLE managed_products; +DROP TABLE external_products; +``` - Nos resultados, veja a propriedade **Location** da tabela, que deve ser um caminho para o armazenamento OneLake do lakehouse que termina com **/Tables/managed_products** (talvez seja necessário ampliar a coluna **Tipo de dados** para ver o caminho completo). +6. No painel do Lakehouse Explorer, **atualize** a pasta Tabelas para verificar se nenhuma tabela está listada no nó Tabelas. +7. No painel do Lakehouse Explorer, **atualize** a pasta Arquivos e verifique se o arquivo external_products *não* foi excluído. Clique nessa pasta para exibir os arquivos de dados do Parquet e a pasta _delta_log. -2. Modifique o comando `DESCRIBE` para mostrar os detalhes da tabela **external_products** conforme mostrado aqui: +Os metadados da tabela externa foram excluídos, mas não o arquivo de dados. - ```sql - %%sql +## Usar o SQL para criar uma tabela Delta - DESCRIBE FORMATTED external_products; - ``` +Agora você criará uma tabela Delta usando o comando magic %%sql. - Nos resultados, veja a propriedade **Location** da tabela, que deve ser um caminho para o armazenamento OneLake do lakehouse que termina com **/Files/external_products** (talvez seja necessário ampliar a coluna **Tipo de dados** para ver o caminho completo). +1. Adicione outra célula de código e execute o seguinte código: + +```python +%%sql +CREATE TABLE products +USING DELTA +LOCATION 'Files/external_products'; +``` - Os arquivos da tabela gerenciada são armazenados na pasta **Tabelas** no armazenamento OneLake do lakehouse. Nesse caso, uma pasta chamada **managed_products** foi criada para armazenar os arquivos Parquet e a pasta **delta_log** para a tabela que você criou. +2. No painel do Lakehouse Explorer, no menu ... da pasta **Tabelas**, clique em **Atualizar**. Em seguida, expanda o nó Tabelas e verifique se uma nova tabela chamada *products* está listada. Em seguida, expanda a tabela para exibir o esquema. 3. Adicione outra célula de código e execute o seguinte código: - ```sql - %%sql +```python +%%sql +SELECT * FROM products; +``` - DROP TABLE managed_products; - DROP TABLE external_products; - ``` +## Explorar o controle de versão de tabela -4. No painel do **Lakehouse Explorer**, no menu **…** da pasta **Tabelas**, selecione **Atualizar**. Em seguida, expanda o nó **Tabelas** e verifique se nenhuma tabela está listada. +O histórico de transações das tabelas Delta é armazenado nos arquivos JSON na pasta delta_log. Você pode usar esse log de transações para gerenciar o controle de versão de dados. -5. No painel do **Lakehouse Explorer**, expanda a pasta **Arquivos** e verifique se **external_products** não foi excluído. Selecione essa pasta para ver os arquivos de dados Parquet e a pasta **_delta_log** dos dados que estavam anteriormente na tabela **external_products**. Os metadados da tabela externa foram excluídos, mas os arquivos não foram afetados. +1. Adicione uma nova célula de código ao notebook e execute o código a seguir, que implementa uma redução de 10% no preço das mountain bikes: -### Usar o SQL para criar uma tabela +```python +%%sql +UPDATE products +SET ListPrice = ListPrice * 0.9 +WHERE Category = 'Mountain Bikes'; +``` -1. Adicione outra célula de código e execute o seguinte código: +2. Adicione outra célula de código e execute o seguinte código: - ```sql - %%sql +```python +%%sql +DESCRIBE HISTORY products; +``` - CREATE TABLE products - USING DELTA - LOCATION 'Files/external_products'; - ``` +Os resultados mostram o histórico de transações registradas para a tabela. -2. No painel do **Lakehouse Explorer**, no menu **…** da pasta **Tabelas**, selecione **Atualizar**. Em seguida, expanda o nó **Tabelas** e verifique se uma nova tabela chamada **products** está listada. Em seguida, expanda a tabela para verificar se o esquema corresponde ao dataframe original que foi salvo na pasta **external_products**. +3. Adicione outra célula de código e execute o seguinte código: -3. Adicione outra célula de código e execute o seguinte código: +```python +delta_table_path = 'Files/external_products' +# Get the current data +current_data = spark.read.format("delta").load(delta_table_path) +display(current_data) - ```sql - %%sql +# Get the version 0 data +original_data = spark.read.format("delta").option("versionAsOf", 0).load(delta_table_path) +display(original_data) +``` - SELECT * FROM products; - ``` +Dois conjuntos de resultado são retornados – um contendo os dados após a redução de preço e o outro mostrando a versão original dos dados. -## Explorar o controle de versão de tabela +## Analisar os dados da tabela Delta com consultas SQL -O histórico de transações das tabelas delta é armazenado em arquivos JSON na pasta **delta_log**. Você pode usar esse log de transações para gerenciar o controle de versão de dados. +Usando o comando magic SQL, você pode usar a sintaxe SQL em vez do Pyspark. Aqui você criará uma exibição temporária da tabela products usando uma instrução `SELECT`. -1. Adicione uma nova célula de código ao notebook e execute o seguinte código: +1. Adicione uma nova célula de código e execute o seguinte código para criar e exibir a exibição temporária: - ```sql - %%sql +```python +%%sql +-- Create a temporary view +CREATE OR REPLACE TEMPORARY VIEW products_view +AS + SELECT Category, COUNT(*) AS NumProducts, MIN(ListPrice) AS MinPrice, MAX(ListPrice) AS MaxPrice, AVG(ListPrice) AS AvgPrice + FROM products + GROUP BY Category; - UPDATE products - SET ListPrice = ListPrice * 0.9 - WHERE Category = 'Mountain Bikes'; - ``` +SELECT * + FROM products_view + ORDER BY Category; + +``` - Esse código implementa uma redução de 10% no preço das mountain bikes. +2. Adicione uma nova célula de código e execute o seguinte código para retornar as dez principais categorias por número de produtos: -2. Adicione outra célula de código e execute o seguinte código: +```python +%%sql +SELECT Category, NumProducts + FROM products_view + ORDER BY NumProducts DESC + LIMIT 10; +``` - ```sql - %%sql +Quando os dados forem retornados, clique na exibição**Gráfico** para exibir um gráfico de barras. - DESCRIBE HISTORY products; - ``` +![Imagem da tela da instrução select SQL e dos resultados.](Images/sql-select.jpg) - Os resultados mostram o histórico de transações registradas para a tabela. +Como alternativa, você pode executar uma consulta SQL usando o PySpark. -3. Adicione outra célula de código e execute o seguinte código: +1. Adicione uma nova célula de código e execute o seguinte código: - ```python - delta_table_path = 'Files/external_products' +```python +from pyspark.sql.functions import col, desc - # Get the current data - current_data = spark.read.format("delta").load(delta_table_path) - display(current_data) +df_products = spark.sql("SELECT Category, MinPrice, MaxPrice, AvgPrice FROM products_view").orderBy(col("AvgPrice").desc()) +display(df_products.limit(6)) +``` - # Get the version 0 data - original_data = spark.read.format("delta").option("versionAsOf", 0).load(delta_table_path) - display(original_data) - ``` +## Usar tabelas Delta para streaming de dados. - Os resultados mostram dois dataframes: um contendo os dados após a redução de preço e o outro mostrando a versão original dos dados. +O Delta Lake permite streaming de dados. As tabelas delta podem ser um coletor ou uma fonte para fluxos de dados criados por meio da API de Streaming Estruturado do Spark. Neste exemplo, você usará uma tabela Delta como um coletor para streaming de dados em um cenário simulado de IoT (Internet das Coisas). -## Usar tabelas delta para transmitir dados +1. Adicione uma nova célula de código, o código a seguir e execute: -O Delta Lake dá suporte a dados de streaming. As tabelas delta podem ser um *coletor* ou uma *fonte* para fluxos de dados criados por meio da API de Streaming Estruturado do Spark. Neste exemplo, você usará uma tabela delta como um coletor para alguns dados de streaming em um cenário simulado de IoT (Internet das Coisas). +```python +from notebookutils import mssparkutils +from pyspark.sql.types import * +from pyspark.sql.functions import * -1. Adicione uma nova célula de código no notebook. Em seguida, na nova célula, adicione o seguinte código e execute-o: +# Create a folder +inputPath = 'Files/data/' +mssparkutils.fs.mkdirs(inputPath) - ```python - from notebookutils import mssparkutils - from pyspark.sql.types import * - from pyspark.sql.functions import * +# Create a stream that reads data from the folder, using a JSON schema +jsonSchema = StructType([ +StructField("device", StringType(), False), +StructField("status", StringType(), False) +]) +iotstream = spark.readStream.schema(jsonSchema).option("maxFilesPerTrigger", 1).json(inputPath) - # Create a folder - inputPath = 'Files/data/' - mssparkutils.fs.mkdirs(inputPath) +# Write some event data to the folder +device_data = '''{"device":"Dev1","status":"ok"} +{"device":"Dev1","status":"ok"} +{"device":"Dev1","status":"ok"} +{"device":"Dev2","status":"error"} +{"device":"Dev1","status":"ok"} +{"device":"Dev1","status":"error"} +{"device":"Dev2","status":"ok"} +{"device":"Dev2","status":"error"} +{"device":"Dev1","status":"ok"}''' - # Create a stream that reads data from the folder, using a JSON schema - jsonSchema = StructType([ - StructField("device", StringType(), False), - StructField("status", StringType(), False) - ]) - iotstream = spark.readStream.schema(jsonSchema).option("maxFilesPerTrigger", 1).json(inputPath) +mssparkutils.fs.put(inputPath + "data.txt", device_data, True) - # Write some event data to the folder - device_data = '''{"device":"Dev1","status":"ok"} - {"device":"Dev1","status":"ok"} - {"device":"Dev1","status":"ok"} - {"device":"Dev2","status":"error"} - {"device":"Dev1","status":"ok"} - {"device":"Dev1","status":"error"} - {"device":"Dev2","status":"ok"} - {"device":"Dev2","status":"error"} - {"device":"Dev1","status":"ok"}''' - mssparkutils.fs.put(inputPath + "data.txt", device_data, True) - print("Source stream created...") - ``` +print("Source stream created...") +``` - Verifique se a mensagem *Fluxo de origem criado…* está impressa. O código que você acabou de executar criou uma fonte de dados de streaming com base em uma pasta na qual alguns dados foram salvos, representando leituras de dispositivos IoT hipotéticos. +Verifique que o texto *Fluxo de origem criado…* será exibido. O código que você acabou de executar criou uma fonte de dados de streaming com base em uma pasta na qual alguns dados foram salvos, representando leituras de dispositivos IoT hipotéticos. 2. Em uma nova célula de código, adicione e execute o seguinte código: - ```python - # Write the stream to a delta table - delta_stream_table_path = 'Tables/iotdevicedata' - checkpointpath = 'Files/delta/checkpoint' - deltastream = iotstream.writeStream.format("delta").option("checkpointLocation", checkpointpath).start(delta_stream_table_path) - print("Streaming to delta sink...") - ``` +```python +# Write the stream to a delta table +delta_stream_table_path = 'Tables/iotdevicedata' +checkpointpath = 'Files/delta/checkpoint' +deltastream = iotstream.writeStream.format("delta").option("checkpointLocation", checkpointpath).start(delta_stream_table_path) +print("Streaming to delta sink...") +``` - Esse código grava os dados do dispositivo de streaming no formato delta em uma pasta chamada **iotdevicedata**. Como o caminho para o local da pasta na pasta **Tabelas**, uma tabela será criada automaticamente para ela. +Esse código grava os dados do dispositivo de streaming no formato Delta em uma pasta chamada iotdevicedata. Como o caminho para o local da pasta na pasta Tabelas, uma tabela será criada automaticamente para ela. 3. Em uma nova célula de código, adicione e execute o seguinte código: - ```sql - %%sql - - SELECT * FROM IotDeviceData; - ``` +```python +%%sql +SELECT * FROM IotDeviceData; +``` - Esse código consulta a tabela **IotDeviceData**, que contém os dados do dispositivo da fonte de streaming. +Esse código consulta a tabela IotDeviceData, que contém os dados do dispositivo da fonte de streaming. 4. Em uma nova célula de código, adicione e execute o seguinte código: - ```python - # Add more data to the source stream - more_data = '''{"device":"Dev1","status":"ok"} - {"device":"Dev1","status":"ok"} - {"device":"Dev1","status":"ok"} - {"device":"Dev1","status":"ok"} - {"device":"Dev1","status":"error"} - {"device":"Dev2","status":"error"} - {"device":"Dev1","status":"ok"}''' +```python +# Add more data to the source stream +more_data = '''{"device":"Dev1","status":"ok"} +{"device":"Dev1","status":"ok"} +{"device":"Dev1","status":"ok"} +{"device":"Dev1","status":"ok"} +{"device":"Dev1","status":"error"} +{"device":"Dev2","status":"error"} +{"device":"Dev1","status":"ok"}''' - mssparkutils.fs.put(inputPath + "more-data.txt", more_data, True) - ``` +mssparkutils.fs.put(inputPath + "more-data.txt", more_data, True) +``` - Esse código grava mais dados hipotéticos do dispositivo na fonte de streaming. +Esse código grava mais dados hipotéticos do dispositivo na fonte de streaming. 5. Execute novamente a célula que contém o seguinte código: - ```sql - %%sql - - SELECT * FROM IotDeviceData; - ``` - - Esse código consulta a tabela **IotDeviceData** novamente, que agora incluirá os dados extras que foram adicionados à fonte de streaming. +```python +%%sql +SELECT * FROM IotDeviceData; +``` -6. Em uma nova célula de código, adicione e execute o seguinte código: +Esse código consulta a tabela IotDeviceData novamente, que agora incluirá os dados extras que foram adicionados à fonte de streaming. - ```python - deltastream.stop() - ``` +6. Em uma nova célula de código, adicione código para interromper o fluxo e execute a célula: - Esse código interrompe o fluxo. +```python +deltastream.stop() +``` ## Limpar os recursos -Neste exercício, você aprendeu a trabalhar com tabelas delta no Microsoft Fabric. +Neste exercício, você aprendeu a trabalhar com tabelas Delta no Microsoft Fabric. -Se você tiver terminado de explorar seu lakehouse, exclua o workspace criado para este exercício. +Se você tiver terminado de explorar seu lakehouse, pode excluir o espaço de trabalho criado para este exercício. 1. Na barra à esquerda, selecione o ícone do workspace para ver todos os itens que ele contém. -2. No menu **…** da barra de ferramentas, selecione **Configurações do workspace**. -3. Na seção **Geral**, selecione **Remover este espaço de trabalho**. +2. No menu ... da barra de ferramentas, clique em **Configurações do Espaço de Trabalho**. +3. Na seção Geral, clique em **Remover este espaço de trabalho**. diff --git a/Instructions/Labs/03b-medallion-lakehouse.md b/Instructions/Labs/03b-medallion-lakehouse.md index b57d405..c8576b3 100644 --- a/Instructions/Labs/03b-medallion-lakehouse.md +++ b/Instructions/Labs/03b-medallion-lakehouse.md @@ -309,10 +309,10 @@ Observe que você poderia ter feito tudo isso em um único notebook, mas para os dfUpdates = dfdimDate_gold - deltaTable.alias('silver') \ + deltaTable.alias('gold') \ .merge( dfUpdates.alias('updates'), - 'silver.OrderDate = updates.OrderDate' + 'gold.OrderDate = updates.OrderDate' ) \ .whenMatchedUpdate(set = { @@ -397,10 +397,10 @@ Observe que você poderia ter feito tudo isso em um único notebook, mas para os dfUpdates = dfdimCustomer_gold - deltaTable.alias('silver') \ + deltaTable.alias('gold') \ .merge( dfUpdates.alias('updates'), - 'silver.CustomerName = updates.CustomerName AND silver.Email = updates.Email' + 'gold.CustomerName = updates.CustomerName AND gold.Email = updates.Email' ) \ .whenMatchedUpdate(set = { @@ -479,10 +479,10 @@ Observe que você poderia ter feito tudo isso em um único notebook, mas para os dfUpdates = dfdimProduct_gold - deltaTable.alias('silver') \ + deltaTable.alias('gold') \ .merge( dfUpdates.alias('updates'), - 'silver.ItemName = updates.ItemName AND silver.ItemInfo = updates.ItemInfo' + 'gold.ItemName = updates.ItemName AND gold.ItemInfo = updates.ItemInfo' ) \ .whenMatchedUpdate(set = { @@ -556,10 +556,10 @@ Observe que você poderia ter feito tudo isso em um único notebook, mas para os dfUpdates = dffactSales_gold - deltaTable.alias('silver') \ + deltaTable.alias('gold') \ .merge( dfUpdates.alias('updates'), - 'silver.OrderDate = updates.OrderDate AND silver.CustomerID = updates.CustomerID AND silver.ItemID = updates.ItemID' + 'gold.OrderDate = updates.OrderDate AND gold.CustomerID = updates.CustomerID AND gold.ItemID = updates.ItemID' ) \ .whenMatchedUpdate(set = { diff --git a/Instructions/Labs/06-data-warehouse.md b/Instructions/Labs/06-data-warehouse.md index 5ac551f..7734060 100644 --- a/Instructions/Labs/06-data-warehouse.md +++ b/Instructions/Labs/06-data-warehouse.md @@ -125,7 +125,7 @@ A maioria das consultas de um data warehouse relacional envolve a agregação e ORDER BY CalendarYear, MonthOfYear; ``` - Observe que os atributos na dimensão temporal permitem agregar as medidas na tabela de fatos em vários níveis hierárquicos, nesse caso, ano e mês. Esse é um padrão comum em data warehouses. + Perceba que os atributos na dimensão de data permitem agregar as medidas na tabela de fatos em vários níveis hierárquicos, nesse caso, ano e mês. Esse é um padrão comum em data warehouses. 2. Modifique a consulta, conforme mostrado a seguir, para adicionar uma segunda dimensão à agregação. @@ -217,7 +217,7 @@ Você pode visualizar com facilidade os dados em uma só consulta ou no data war - **ProductKey** - **ProductAltKey** -1. Agora você está pronto para criar um relatório e disponibilizar esse conjunto de dados para outras pessoas. No menu Página Inicial, selecione **Novo relatório**. Isso abrirá uma nova janela, na qual você poderá criar um relatório do Power BI. +1. Agora você está pronto para criar um relatório e disponibilizar esse conjunto de dados para outras pessoas. No menu Relatório, clique em **Novo relatório**. Isso abrirá uma nova janela, na qual você poderá criar um relatório do Power BI. 1. No painel **Dados**, expanda **FactSalesOrder**. Observe que as colunas que você escondeu não estão mais visíveis.