Dataframe no Apache PySpark: tutorial abrangente [com exemplos]

Publicados: 2020-02-27

Hoje, vamos aprender sobre o DataFrame no Apache PySpark . O Pyspark é uma das principais ferramentas de ciência de dados em 2020. Ele é chamado de colunas de uma coleção distribuída de linhas no Apache Spark. É muito semelhante às Tabelas ou colunas em planilhas do Excel e também semelhante à tabela do banco de dados relacional. O PySpark DataFrame também possui características semelhantes do RDD, que são:

Distribuído: A natureza do DataFrame e do RDD é distribuída

Avaliações preguiçosas: a execução da tarefa não é feita se a ação não for realizada

Natureza do Imutável: Outra característica semelhante do RDD/DataFrame é que ele não pode ser alterado depois de criado. Mas pode-se aplicar a transformação para transformar o RDD/DataFrame.

Índice

Vantagem dos DataFrames

1. Isso suporta várias linguagens, como Java, Scala, R, Python, o que é útil em termos de suporte de API. O suporte de API para vários idiomas ajuda a trabalhar com muitas linguagens de programação.

2. Uma ampla gama de fontes e formatos de dados são suportados pelo DataFrame, o que ajuda muito a usar uma fonte diferente de dados e seu formato de forma conveniente.

3. Uma das melhores partes do DataFrame é que ele pode até mesmo lidar com petabytes de dados, o que é uma habilidade notável para lidar com dados tão grandes.

4. O Apache Spark compreende rapidamente o esquema do DataFrame com a observação no Spark DataFrame. Em colunas nomeadas, a Observação do Spark DataFrame é organizada. Desta forma, o plano de execução das consultas é otimizado.

5. Volume Massivo de Dados Estruturados e Semi-estruturados pode ser rapidamente processado porque é projetado para fazê-lo DataFrames.

Configuração do Apache Spark

O Apache Spark deve ser configurado na máquina antes que possa ser iniciado para uso em Operações DataFrame. Os dados podem ser operados com o suporte do DataFrame, pois ele suporta várias operações do DataFrame. Aqui vamos discutir algumas operações comuns do DataFrame.

A criação do SparkContext é o primeiro passo na programação do Apache. Para a execução de operações em um cluster, há um requisito de SparkContext. Como acessar um cluster é informado pelo SparkContext. Ele também mostra o Spark sobre o local para obter um cluster.

Leia: Estruturas de aprendizado profundo

Em seguida, a conexão do Apache Cluster é estabelecida. Sua criação já está feita se estiver usando o Spark Shell. A outra forma, a definição de configuração, pode ser fornecida, inicializada e importada para a criação do SparkContext.

Pode-se usar este código para a criação:

do pyspark import SparkContext

sc = SparkContext()

Criação de DataFrame a partir do arquivo CSV

Uma nova biblioteca deve ser especificada no shell do python para que o arquivo CSV possa ser lido. Para isso, o primeiro passo é baixar a versão mais recente do pacote Spark-CSV e fazer a extração do pacote no Home Directory do Spark. Depois disso, abriremos o shell do PySpark e o pacote deve ser incluído.

$ ./bin/pyspark –packages com.databricks:spark-csv_2.10:1.3.0

Agora o DataFrame será criado após a leitura dos dados do arquivo CSV.

train = sqlContext.load(source=”com.databricks.spark.csv”, caminho = 'PATH/train.csv', header = True,inferSchema = True)

test = sqlContext.load(source=”com.databricks.spark.csv”, caminho = 'PATH/test-comb.csv', header = True,inferSchema = True)

Os arquivos CSV de teste e os arquivos CSV de treinamento estão localizados no local da pasta chamado PATH. Se o cabeçalho estiver no arquivo CSV, ele será exibido como True. Para saber o tipo de dado em cada coluna do data frame, usaremos a opção inferSchema = True. Ao usar a opção inferSchema = True, a detecção do tipo de dados do quadro de dados de cada coluna será detectada automaticamente pelo contexto SQL. Todas as colunas serão lidas como uma string Se não definirmos inferSchema como true.

Leia: Bibliotecas Python para Aprendizado de Máquina

Manipulação de DataFrame

Agora vamos ver como manipular o Data Frame:

  • Conheça o tipo de dados das colunas

printSchema será usado para ver o tipo de coluna e seu tipo de dados. Agora o esquema será impresso em formato de árvore aplicando o printSchema().

train.printSchema()

Saída:

raiz

|– User_ID: inteiro (anulável = verdadeiro)

|– Product_ID: string (anulável = true)

|– Gênero: string (anulável = true)

|– Idade: string (anulável = true)

|– Ocupação: inteiro (anulável = verdadeiro)

|– City_Category: string (anulável = true)

|– Stay_In_Current_City_Years: string (anulável = true)

|– Estado_conjugal: inteiro (anulável = verdadeiro)

|– Product_Category_1: integer (anulável = true)

|– Product_Category_2: integer (anulável = true)

|– Product_Category_3: integer (anulável = true)

|– Compra: inteiro (anulável = verdadeiro)

Após a leitura do arquivo de csv, podemos ver que obtivemos com precisão o tipo de dado ou o esquema de cada coluna no data frame.

  • Mostrando a primeira n observação

Para ver a primeira n observação, pode-se usar a operação de cabeça. A operação da cabeça do Pandas é a mesma da operação da cabeça do PySpark.

train.head(5)

Saída:

[Row(User_ID=1000001, Product_ID=u'P00069042′, Gender=u'F', Age=u'0-17′, Occupation=10, City_Category=u'A', Stay_In_Current_City_Years=u'2′, Marital_Status= 0, Product_Category_1=3, Product_Category_2=Nenhum, Product_Category_3=Nenhum, Compra=8370),

Row(User_ID=1000001, Product_ID=u'P00248942′, Gender=u'F', Age=u'0-17′, Occupation=10, City_Category=u'A', Stay_In_Current_City_Years=u'2′, Marital_Status=0 , Product_Category_1=1, Product_Category_2=6, Product_Category_3=14, Purchase=15200),

Row(User_ID=1000001, Product_ID=u'P00087842′, Gender=u'F', Age=u'0-17′, Occupation=10, City_Category=u'A', Stay_In_Current_City_Years=u'2′, Marital_Status=0 , Product_Category_1=12, Product_Category_2=Nenhum, Product_Category_3=Nenhum, Compra=1422),

Row(User_ID=1000001, Product_ID=u'P00085442′, Gender=u'F', Age=u'0-17′, Occupation=10, City_Category=u'A', Stay_In_Current_City_Years=u'2′, Marital_Status=0 , Product_Category_1=12, Product_Category_2=14, Product_Category_3=Nenhum, Compra=1057),

Row(User_ID=1000002, Product_ID=u'P00285442′, Gender=u'M', Age=u'55+', Occupation=16, City_Category=u'C', Stay_In_Current_City_Years=u'4+', Marital_Status=0 , Product_Category_1=8, Product_Category_2=Nenhum, Product_Category_3=Nenhum, Compra=7969)]

Agora vamos usar a operação show para ver o resultado de uma maneira melhor, pois os resultados virão no formato de linha. Também podemos truncar o resultado usando o argumento truncate = True.

train.show(2,truncate= True)

Saída:

+——-+———-+——+—-+———-+————-+————————–+————–+——————+ ——————+——————+——–+

|User_ID|Product_ID|Gender| Idade|Ocupação|City_Category|Stay_In_Current_City_Years|Marital_Status|Product_Category_1|Product_Category_2|Product_Category_3|Compra|

+——-+———-+——+—-+———-+————-+————————–+————–+——————+ ——————+——————+——–+

|1000001| P00069042| F|0-17| 10| A| 2| 0| 3| null| null| 8370|

|1000001| P00248942| F|0-17| 10| A| 2| 0| 1| 6| 14| 15200|

+——-+———-+——+—-+———-+————-+————————–+————–+——————+ ——————+——————+——–+

mostrando apenas as 2 primeiras linhas

  • Contagem do número de linhas do DataFrame

Para contar o número de linhas no quadro de dados, podemos usar a operação de contagem. Agora contaremos o número de linhas de arquivos de teste e arquivos de treinamento aplicando a operação de contagem.

train.count(),test.count()

Saída:

(233598, 550069)

Temos 233598, 550069, linhas em teste e treinamento, respectivamente.

  • Obtendo a contagem da coluna e o nome das colunas do arquivo de teste e treinamento

Semelhante à operação da coluna no DataFrame dos pandas, usaremos a operação de colunas para obter o nome da coluna. Agora primeiro vamos imprimir o não. da coluna e o nome da coluna do arquivo de teste e do arquivo de treinamento.

len(trem.colunas), trem.colunas

Saída:

12 ['User_ID', 'Product_ID', 'Gender', 'Age', 'Occupation', 'City_Category', 'Stay_In_Current_City_Years', 'Marital_Status', 'Product_Category_1', 'Product_Category_2', 'Product_Category_3', 'Purchase']

Agora estamos fazendo isso para o arquivo de teste da mesma forma.

len(teste.colunas), teste.colunas

Saída:

13 [”, 'User_ID', 'Product_ID', 'Gender', 'Age', 'Occupation', 'City_Category', 'Stay_In_Current_City_Years', 'Marital_Status', 'Product_Category_1', 'Product_Category_2', 'Product_Category_3', 'Comb ']

Após a saída acima, podemos ver que existem 12 colunas no arquivo de treinamento e 13 colunas no arquivo de teste. A partir da saída acima, podemos verificar que temos 13 colunas no arquivo de teste e 12 no arquivo de treinamento. A coluna “Comb” é a única coluna no arquivo de teste e não há “Purchase” não presente no arquivo de teste. Há mais uma coluna no arquivo de teste que podemos ver que não tem nenhum nome da coluna.

  • Obtendo as estatísticas resumidas, como contagem, máximo, mínimo, desvio padrão, média nas colunas numéricas do DataFrame

No DataFrame, usaremos a operação chamada descrever a operação. Podemos fazer o cálculo da coluna numérica e obter um resumo estatístico usando descrever a operação. Todas as colunas numéricas serão calculadas no DataFrame, não há nome de coluna especificado no cálculo das estatísticas de resumo.

treinar.descrever().mostrar()

Saída:

+——-+——————+—————+——————-+——————+——————+——————+—— ————+

|resumo| User_ID| Ocupação| Status_conjugal|Product_Category_1|Product_Category_2|Product_Category_3| Compra|

+——-+——————+—————+——————-+——————+——————+——————+—— ————+

| contar| 550068| 550068| 550068| 550068| 376430| 166821| 550068|

| média|1003028.8424013031|8,076706879876669|0,40965298835780306| 5.404270017525106| 9.842329251122386|12.668243206790512| 9263.968712959126|

| stddev|1727.5915855308265|6.522660487341778| 0,4917701263173273|3,9362113692014082| 5.086589648693526| 4.125337631575267|5023.0653938206015|

| min| 1000001| 0| 0| 1| 2| 3| 12|

| max| 1006040| 20| 1| 20| 18| 18| 23961|

+——-+——————+—————+——————-+——————+——————+——————+—— ————+

Na operação de descrição, isso é o que obtemos quando o nome da coluna de string ou o nome da coluna categórica é especificado.

train.describe('Product_ID').show()

Saída:

+——-+———-+

|resumo|Produto_ID|

+——-+———-+

| contar| 550068|

| significa | null|

| stddev| null|

| min| P00000142|

| max| P0099942|

+——-+———-+

Com base em ASCII, os valores máximo e mínimo calculados. A operação de descrição é usada para trabalhar na coluna do tipo String.

  • Seleção da coluna do DataFrame

Usaremos o nome das colunas na operação de seleção para selecionar a coluna. Mencionaremos o nome da coluna com a separação usando vírgulas. Agora vamos ver como é feita a seleção de “Age” e “User_ID” do arquivo de treinamento.

  • train.select('User_ID','Idade').show(5)
  • Saída:
  • +——-+—-+
  • |User_ID| Idade|
  • +——-+—-+
  • |1000001|0-17|
  • |1000001|0-17|
  • |1000001|0-17|
  • |1000001|0-17|
  • |1000002| 55+|
  • +——-+—-+
  • Encontrando produto distinto no. em arquivos de teste e arquivos de trem

Para calcular o nº do DataFrame. de linhas distintas, usaremos a operação distinct . Agora aqui vamos aplicar uma operação distinta para o cálculo de no. de produto distinto em arquivo de teste e trem.

train.select('Product_ID').distinct().count(),test.select('Product_ID').distinct().count()

Saída:

(3633, 3492)

Temos 3492 e 3633 produtos distintos em arquivo de teste e treinamento, respectivamente. Agora sabemos que no arquivo de treinamento, temos valores mais distintos do que no arquivo de teste, pois podemos aprender com o resultado de saída. Agora usaremos a operação de subtração para descobrir as categorias Product_ID que não estão presentes no arquivo de treinamento, mas estão presentes no arquivo de teste. A mesma coisa que se pode fazer para todos os recursos do categórico.

diff_cat_in_train_test=test.select('Product_ID').subtract(train.select('Product_ID'))

diff_cat_in_train_test.distinct().count()# Para contagem distinta

Saída:

46

Portanto, a partir do resultado acima, podemos saber que existem 47 categorias diferentes, que não estão presentes no arquivo de treinamento, mas estão presentes no arquivo de teste. Os dados serão ignorados ou coletados do arquivo de teste, que não está presente no arquivo do trem.

  • Cálculo da frequência de pares de colunas categóricas?

Vamos fazer o cálculo da frequência de pares da coluna no DataFrame usando a operação can crosstab. Agora vamos calcular as colunas “Gender” e “Age” no DataFrame do trem aplicando a operação de crosstab .

train.crosstab('Idade', 'Sexo').show()

Saída:

+———-+—–+——+

|Idade_Gênero| F| M|

+———-+—–+——+

| 0-17| 5083| 10019|

| 46-50|13199| 32502|

| 18-25|24628| 75032|

| 36-45|27170| 82843|

| 55+| 5083| 16421|

| 51-55| 9894| 28607|

| 26-35|50752|168835|

+———-+—–+——+

O valor distinto de Gender é o nome da coluna, e a quantidade diferente de Age é o nome da linha, que pode ser visto no resultado acima. Na tabela, a contagem do par será zero caso não tenha ocorrido.

Como obter DataFrame com linhas exclusivas?

Para encontrar linhas exclusivas e não incluir linhas duplicadas, usaremos a operação dropDuplicates . Ele obterá o Dataframe sem nenhuma linha duplicada, descartando as linhas duplicadas de um DataFrame. Por favor, verifique aqui para saber como o procedimento dropDuplicates é executado para obter todas as linhas exclusivas para as colunas.

train.select('Idade','Gênero').dropDuplicates().show()

Saída:

+—–+——+

| Idade|Sexo|

+—–+——+

|51-55| F|

|51-55| M|

|26-35| F|

|26-35| M|

|36-45| F|

|36-45| M|

|46-50| F|

|46-50| M|

| 55+| F|

| 55+| M|

|18-25| F|

| 0-17| F|

|18-25| M|

| 0-17| M|

+—–+——+

  • Como descartar linhas terá valor nulo?

Se alguém quiser descartar todas as linhas que têm um valor nulo, podemos usar a operação chamada operação dropna . Para remover a linha do DataFrame, ele considera três opções.

  • Subconjunto – é a lista de todos os nomes das colunas a serem consideradas para a operação de eliminação de colunas com valores nulos.
  • Thresh – isso ajuda a eliminar as linhas com valores não nulos inferiores a thresh. Por padrão, nada é especificado neste.
  • Como – Pode ser usado em dois tipos – todos ou qualquer um. Ao usar qualquer, ele descartará a linha se qualquer valor na linha for nulo. Ao usar all, diminuirá a linha se os valores de todas as linhas forem nulos.

Agora, aqui vamos usar todas essas opções uma a uma para descartar as linhas que são nulas usando opções padrão como subconjunto, thresh, Nenhum para como, nenhum, qualquer.

train.dropna().count()

Saída:

166821

  • Como preencher os valores nulos do DataFrame com a constante no.?

Para preencher os valores nulos com a constante no. Usaremos a operação fillna aqui. Existem dois parâmetros a serem considerados pela operação fillna para preencher os valores nulos.

  • subconjunto: Aqui, é preciso especificar as colunas a serem consideradas para o preenchimento dos valores.
  • valor: Aqui, podemos citar a quantidade a ser substituída por qual valor, que pode ser qualquer tipo de dado como string, float, int em todas as colunas.

Aqui vamos preencher '-1' no lugar de valores nulos em train DataFrame.

train.fillna(-1).show(2)

Saída:

+——-+———-+——+—-+———-+————-+————————–+————–+——————+ ——————+——————+——–+

|User_ID|Product_ID|Gender| Idade|Ocupação|City_Category|Stay_In_Current_City_Years|Marital_Status|Product_Category_1|Product_Category_2|Product_Category_3|Compra|

+——-+———-+——+—-+———-+————-+————————–+————–+——————+ ——————+——————+——–+

|1000001| P00069042| F|0-17| 10| A| 2| 0| 3| -1| -1| 8370|

|1000001| P00248942| F|0-17| 10| A| 2| 0| 1| 6| 14| 15200|

+——-+———-+——+—-+———-+————-+————————–+————–+——————+ ——————+——————+——–+

mostrando apenas as 2 primeiras linhas

Conclusão

O PySpark está ganhando força no mundo da Inteligência Artificial e Machine Learning. O PySpark é usado para resolver problemas de aprendizado de máquina do mundo real. Você pode criar RDD de diferentes fontes de dados externas e existentes e fazer todos os tipos de transformações nele. Espero que este artigo tenha sido informativo e possa fornecer insights profundos sobre os dataframes do PySpark.

Se você estiver curioso para aprender sobre o PySpark e outras ferramentas de ciência de dados, confira o PG Diploma in Data Science do IIIT-B & upGrad, criado para profissionais que trabalham e oferece mais de 10 estudos de caso e projetos, workshops práticos práticos, orientação com especialistas do setor, 1-on-1 com mentores do setor, mais de 400 horas de aprendizado e assistência de trabalho com as principais empresas.

O PySpark é mais eficiente que o Pandas?

Sim, o PySpark é mais rápido que o Pandas e até supera o Pandas em um teste de benchmarking. Em termos básicos, o Pandas realiza operações em uma única máquina, enquanto o PySpark executa operações em várias máquinas. Se você estiver trabalhando em um aplicativo de aprendizado de máquina com um grande conjunto de dados, o PySpark é a opção ideal, pois pode executar operações 100 vezes mais rápido que o Pandas. Por causa da JVM, a linguagem de programação Scala é 10 vezes mais rápida que o Python para análise e processamento de dados. Quando o código de programação Python é utilizado para fazer chamadas para bibliotecas Spark, os resultados são medíocres.

Quais são algumas das desvantagens de usar o Apache PySpark?

O Spark não possui seu próprio sistema de gerenciamento de arquivos. Devido ao alto custo de memória extra necessária para operar o Spark, a computação na memória pode ser proibitivamente cara. Ao utilizar o Apache Spark com o Hadoop, os desenvolvedores encontram dificuldades com arquivos compactos. Os dados são iterados em lotes no Spark, com cada iteração sendo planejada e processada de forma independente. No Apache Spark, os dados são divididos em lotes menores em um intervalo de tempo predeterminado. Como resultado, os critérios de janela baseados em registro não serão suportados pelo Apache. Em vez disso, fornece critérios de janela baseados em tempo.

Como Datasets, DataFrame e RDD são diferentes entre si?

RDD é uma coleção agrupada de itens de dados dispersos em vários computadores. Os dados são representados por meio de RDDs, que são uma coleção de objetos Java ou Scala. Um DataFrame é uma coleção de dados estruturados em colunas nomeadas espalhadas por vários servidores. Em um banco de dados relacional, é conceitualmente equivalente a uma tabela. Dataset é uma extensão de API de dataframe que oferece a capacidade de interface de programação orientada a objetos e de tipo seguro da API RDD. Um DataFrame é uma coleção distribuída de dados, semelhante a um RDD, e não é mutável. Os dados são estruturados em colunas nomeadas, semelhantes a uma tabela em um banco de dados relacional, em vez de um RDD. Quando se trata de tarefas simples, como agrupar dados, o RDD é mais lento que Dataframes e Datasets. Possui uma API simples para realizar tarefas agregadas. Ele pode agregar dados mais rapidamente que RDDs e Datasets.