EXEMPLO: transformações Flatten e Unnest

Origem:

Você tem dados sobre as pontuações dos testes dos alunos. As pontuações individuais são armazenadas na matriz Scores, e você precisa acompanhar cada teste em uma linha exclusivamente identificável. Este exemplo tem dois objetivos:

  1. Uma linha para cada teste de aluno.
  2. Um identificador exclusivo para cada combinação aluno-pontuação.
LastNameFirstNameScores
AdamsAllen[81,87,83,79]
BurnsBonnie[98,94,92,85]
CannonCharles[88,81,85,78]

Transformação:

Quando os dados são importados no formato CSV, é necessário adicionar uma transformação header e remover as aspas da coluna Scores:

header

replace col:Scores with:'' on:`"` global:true

Validar a data do teste: para começar, verifique se você tem a quantidade adequada de pontuações de teste para cada aluno. Use a seguinte transformação para calcular a diferença entre o número esperado de elementos na matriz Scores (4) e o número real:

derive type:single value: (4 - ARRAYLEN(Scores)) as: 'numMissingTests'

Quando a transformação for visualizada, será possível ver, no conjunto de dados da amostra, que todos os testes foram incluídos. Você decide se quer ou não incluir essa coluna no conjunto de dados final, já que pode identificar testes ausentes quando a receita é executada em escala.

Identificador de linha único: é preciso dividir a matriz Scores em linhas individuais para cada teste. No entanto, não há identificador único para que a linha faça o rastreamento dos testes individuais. Em teoria, você poderia usar a combinação dos valores LastName-FirstName-Scores para fazer isso, mas, se um aluno tiver gravado o mesmo resultado duas vezes, o conjunto de dados ficará com linhas duplicadas. Na transformação a seguir, você cria uma matriz paralela chamada Tests, que contém uma matriz de índice para o número de valores na coluna Scores. Os valores do índice começam em 0.

derive type:single value:RANGE(0,ARRAYLEN(Scores)) as:'Tests'

Além disso, criaremos um identificador para a linha de origem usando a função SOURCEROWNUMBER:

derive type:single value:SOURCEROWNUMBER() as:'orderIndex'

Uma linha para cada teste de aluno: seus dados terão esta aparência:

LastNameFirstNameScoresTestsorderIndex
AdamsAllen[81,87,83,79][0,1,2,3]2
BurnsBonnie[98,94,92,85][0,1,2,3]3
CannonCharles[88,81,85,78][0,1,2,3]4

Agora, reúna as matrizes Tests e Scores em uma única matriz aninhada usando a função ARRAYZIP:

derive type:single value:ARRAYZIP([Tests,Scores])

O conjunto de dados foi alterado:

LastNameFirstNameScoresTestsorderIndexcolumn1
AdamsAllen[81,87,83,79][0,1,2,3]2[[0,81],[1,87],[2,83],[3,79]]
AdamsBonnie[98,94,92,85][0,1,2,3]3[[0,98],[1,94],[2,92],[3,85]]
CannonCharles[88,81,85,78][0,1,2,3]4[[0,88],[1,81],[2,85],[3,78]]

Com a transformação flatten, é possível descompactar a matriz aninhada:

flatten col: column1

Cada combinação teste-pontuação agora é dividida em uma linha separada. As combinações teste-pontuação aninhadas precisam ser divididas em colunas separadas com o uso de unnest:

unnest col:column1 keys:'[0]','[1]'

Depois de excluir a column1, que não é mais necessária, renomeie as duas colunas geradas:

rename mapping:[column_0,'TestNum']

rename mapping:[column_1,'TestScore']

Identificador exclusivo de linha: é possível executar mais uma etapa para criar identificadores exclusivos de teste, identificando o teste específico para cada aluno. Veja a seguir como o identificador de linha original OrderIndex é usado como um identificador para o aluno, e o valor TestNumber para criar o valor da coluna TestId:

derive type:single value: (orderIndex * 10) + TestNum as: 'TestId'

Os valores acima são números inteiros. Para melhorar a aparência dos seus identificadores, adicione o texto a seguir:

merge col:'TestId00','TestId'


Extensão:
talvez seja útil gerar algumas informações estatísticas resumidas neste conjunto de dados. Por exemplo, você pode estar interessado em calcular a pontuação média dos testes de cada aluno. Nesta etapa, é necessário descobrir como agrupar adequadamente os valores dos testes. Nesse caso, não é possível agrupar pelo valor LastName e, quando executado em escala, poderá haver colisões entre os nomes quando essa receita for executada dessa forma. Portanto, talvez seja necessário criar um tipo de chave primária usando:

merge col:'LastName','FirstName' with:'-' as:'studentId'

Agora, use isto como um parâmetro de agrupamento para seu cálculo:

derive type:single value:AVERAGE(TestScore) group:studentId as:'avg_TestScore'

Resultados:

Depois de excluir as colunas desnecessárias e mover as outras, o conjunto de dados será semelhante ao seguinte:

TestIdLastNameFirstNameTestNumTestScorestudentIdavg_TestScore
TestId0021AdamsAllen081Adams-Allen82,5
TestId0022AdamsAllen187Adams-Allen82,5
TestId0023AdamsAllen283Adams-Allen82,5
TestId0024AdamsAllen379Adams-Allen82,5
TestId0031AdamsBonnie098Adams-Bonnie92,25
TestId0032AdamsBonnie194Adams-Bonnie92,25
TestId0033AdamsBonnie292Adams-Bonnie92,25
TestId0034AdamsBonnie385Adams-Bonnie92,25
TestId0041CannonChris088Cannon-Chris83
TestId0042CannonChris181Cannon-Chris83
TestId0043CannonChris285Cannon-Chris83
TestId0044CannonChris378Cannon-Chris83
Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Documentação do Google Cloud Dataprep
Precisa de ajuda? Acesse nossa página de suporte.