복붙노트

[PYTHON] 숫자가 아닌 열에서 피벗을 사용하고 평균을 계산하는 방법 (AnalysisException "숫자 열이 아닌")?

PYTHON

숫자가 아닌 열에서 피벗을 사용하고 평균을 계산하는 방법 (AnalysisException "숫자 열이 아닌")?

다음과 같은 데이터 프레임이 있습니다.

rdd = sc.parallelize(
    [
        (0, "A", 223,"201603", "PORT"), 
        (0, "A", 22,"201602", "PORT"), 
        (0, "A", 422,"201601", "DOCK"), 
        (1,"B", 3213,"201602", "DOCK"), 
        (1,"B", 3213,"201601", "PORT"), 
        (2,"C", 2321,"201601", "DOCK")
    ]
)
df_data = sqlContext.createDataFrame(rdd, ["id","type", "cost", "date", "ship"])

df_data.show()
+---+----+----+------+----+
| id|type|cost|  date|ship|
+---+----+----+------+----+
|  0|   A| 223|201603|PORT|
|  0|   A|  22|201602|PORT|
|  0|   A| 422|201601|DOCK|
|  1|   B|3213|201602|DOCK|
|  1|   B|3213|201601|PORT|
|  2|   C|2321|201601|DOCK|
+---+----+----+------+----+

ID 및 유형 그룹에 대한 비용 평균을 계산하고 날짜에 피벗하면 예상대로 작동합니다.

+---+----+------+------+------+
| id|type|201601|201602|201603|
+---+----+------+------+------+
|  2|   C|2321.0|  null|  null|
|  0|   A| 422.0|  22.0| 223.0|
|  1|   B|3213.0|3213.0|  null|
+---+----+------+------+------+

이제 나는 선박 컬럼의 평균값 (비 숫자 컬럼)을 계산하여 다음과 같은 결과를 얻고 싶습니다 :

// NOTE: The following query fails
df_data.groupby(df_data.id, df_data.type).pivot("date").avg("ship").show()
+---+----+------+------+------+
| id|type|201601|201602|201603|
+---+----+------+------+------+
|  2|   C|  DOCK|  null|  null|
|  0|   A|  DOCK|  PORT|  DOCK|
|  1|   B|  DOCK|  PORT|  null|
+---+----+------+------+------+

그러나 다음 예외가 발생합니다.

피벗과 함께 가능합니까?

해결법

  1. ==============================

    1.(id | type | date) 조합이 고유하고 유일한 목표는 집계가 아니라 피벗 팅이라고 가정하고 먼저 사용할 수 있습니다 (또는 숫자 값에 제한되지 않는 다른 함수).

    (id | type | date) 조합이 고유하고 유일한 목표는 집계가 아니라 피벗 팅이라고 가정하고 먼저 사용할 수 있습니다 (또는 숫자 값에 제한되지 않는 다른 함수).

    from pyspark.sql.functions import first
    
    (df_data
        .groupby(df_data.id, df_data.type)
        .pivot("date")
        .agg(first("ship"))
        .show())
    
    ## +---+----+------+------+------+
    ## | id|type|201601|201602|201603|
    ## +---+----+------+------+------+
    ## |  2|   C|  DOCK|  null|  null|
    ## |  0|   A|  DOCK|  PORT|  PORT|
    ## |  1|   B|  PORT|  DOCK|  null|
    ## +---+----+------+------+------+
    

    이러한 가정이 정확하지 않으면 데이터를 사전 집계해야합니다. 가장 일반적인 선박 가치의 예를 들면 :

    from pyspark.sql.functions import max, struct
    
    (df_data
        .groupby("id", "type", "date", "ship")
        .count()
        .groupby("id", "type")
        .pivot("date")
        .agg(max(struct("count", "ship")))
        .show())
    
    ## +---+----+--------+--------+--------+
    ## | id|type|  201601|  201602|  201603|
    ## +---+----+--------+--------+--------+
    ## |  2|   C|[1,DOCK]|    null|    null|
    ## |  0|   A|[1,DOCK]|[1,PORT]|[1,PORT]|
    ## |  1|   B|[1,PORT]|[1,DOCK]|    null|
    ## +---+----+--------+--------+--------+
    
  2. from https://stackoverflow.com/questions/37486910/how-to-use-pivot-and-calculate-average-on-a-non-numeric-column-facing-analysise by cc-by-sa and MIT license