El modo de agrupar los datos en (py)Spark

Tengo un spark DataFrame con varias columnas. Me gustaría grupo de las filas basadas en una columna y, a continuación, encontrar el modo de la segunda columna para cada grupo. Trabajando con un pandas DataFrame, me gustaría hacer algo como esto:

rand_values = np.random.randint(max_value,
                                size=num_values).reshape((num_values/2, 2))
rand_values = pd.DataFrame(rand_values, columns=['x', 'y'])
rand_values['x'] = rand_values['x'] > max_value/2
rand_values['x'] = rand_values['x'].astype('int32')

print(rand_values)
##    x  y
## 0  0  0
## 1  0  4
## 2  0  1
## 3  1  1
## 4  1  2

def mode(series):
    return scipy.stats.mode(series['y'])[0][0]

rand_values.groupby('x').apply(mode)
## x
## 0    4
## 1    1
## dtype: int64

Dentro de pyspark, soy capaz de encontrar el modo de una sola columna haciendo

df = sql_context.createDataFrame(rand_values)

def mode_spark(df, column):
    # Group by column and count the number of occurrences
    # of each x value
    counts = df.groupBy(column).count()

    # - Find the maximum value in the 'counts' column
    # - Join with the counts dataframe to select the row
    #   with the maximum count
    # - Select the first element of this dataframe and
    #   take the value in column
    mode = counts.join(
        counts.agg(F.max('count').alias('count')),
        on='count'
    ).limit(1).select(column)

    return mode.first()[column]

mode_spark(df, 'x')
## 1
mode_spark(df, 'y')
## 1

Estoy en una pérdida para saber cómo aplicar la función para datos agrupados. Si no es posible aplicar directamente esta lógica a un DataFrame, es posible lograr el mismo efecto por algún otro medio?

Gracias de antemano!

  • Grupo por (x, y), agregado con el conde, seleccione max fila, como se muestra a continuación: stackoverflow.com/a/35226857/1560062
  • Gracias por la rápida respuesta! Voy a probar esto!
  • Que parece que funcionó! Es posible para mí para agregar mi solución, pero que marca como el «contestador»?
  • Sólo tienes que ir adelante y la respuesta no me importa. Puede vincular el original de la respuesta en la pregunta como una referencia. Y usted puede upvote otra respuesta cuando usted consigue el privilegio requerido 🙂
InformationsquelleAutor bjack3 | 2016-04-15

1 Kommentar

  1. 9

    Solución sugerida por zero323.

    Solución Original: https://stackoverflow.com/a/35226857/1560062

    Primero, contar las ocurrencias de cada (x, y) combinación.

    counts = df.groupBy(['x', 'y']).count().alias('counts')
    counts.show()
    ## +---+---+-----+
    ## |  x|  y|count|
    ## +---+---+-----+
    ## |  0|  1|    2|
    ## |  0|  3|    2|
    ## |  0|  4|    2|
    ## |  1|  1|    3|
    ## |  1|  3|    1|
    ## +---+---+-----+

    Solución 1: Grupo de ‘x’, agregado por tomar el valor máximo de la cuenta en cada grupo. Por último, la Caída de la ‘contar’ columna.

    result = (counts
              .groupBy('x')
              .agg(F.max(F.struct(F.col('count'),
                                  F.col('y'))).alias('max'))
              .select(F.col('x'), F.col('max.y'))
             )
    result.show()
    ## +---+---+
    ## |  x|  y|
    ## +---+---+
    ## |  0|  4|
    ## |  1|  1|
    ## +---+---+

    Solución 2: Uso de una ventana, partición de ‘x’, y orden del ‘conde’ de la columna. Ahora, elija la primera fila en cada una de las particiones.

    win = Window().partitionBy('x').orderBy(F.col('count').desc())
    result = (counts
              .withColumn('row_num', F.rowNumber().over(win))
              .where(F.col('row_num') == 1)
              .select('x', 'y')
             )
    result.show()
    ## +---+---+
    ## |  x|  y|
    ## +---+---+
    ## |  0|  1|
    ## |  1|  1|
    ## +---+---+

    Los dos resultados, tienen un resultado diferente debido a la forma en que las filas se ordenan. Si no hay lazos, los dos métodos dan el mismo resultado.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea