Добавить столбец в набор данных на основе значения из другого набора данных - PullRequest
0 голосов
/ 22 мая 2019

У меня есть набор данных dsCustomer, в котором есть данные о клиенте со столбцами

|customerID|idpt | totalAmount|
|customer1 | H1  |    250     |
|customer2 | H2  |    175     |
|customer3 | H3  |    4000    |
|customer4 | H3  |    9000    |

У меня есть другой набор данных dsCategory, который содержит категорию на основе объема продаж

|categoryID|idpt | borne_min|borne_max|
|A         |  H2 | 0        |1000     |
|B         |  H2 | 1000     |5000     |
|C         |  H2 | 5000     |7000     |
|D         |  H2 | 7000     |10000    |
|F         |  H3 | 0        |1000     |
|G         |  H3 | 1000     |5000     |
|H         |  H3 | 5000     |7000     |
|I         |  H3 | 7000     |1000000  |


Мне бы хотелосьчтобы получить результат, который принимает totalAmount клиента и найти категорию.

|customerID|idpt |totalAmount|category|
|customer1 | H1  |   250     | null   |
|customer2 | H2  |   175     | A      |
|customer3 | H3  |   4000    | G      |
|customer4 | H3  |   9000    | I      |
//udf 
public static Column getCategoryAmount(Dataset<Row> ds, Column amountColumn) {
        return ds.filter(amountColumn.geq(col("borne_min"))
                .and(amountColumn.lt(col("borne_max")))).first().getAs("categoryID");

    }

//code to add column to my dataset
dsCustomer.withColumn("category", getCategoryAmount(dsCategory , dsCustomer.col("totalAmount")));

Как я могу передать значение столбца из моего набора данных клиента в мою функцию UDF

Поскольку ошибка показывает, что totalAmount не содержится в наборе данных категории

Вопрос: Как я могу использовать Map для каждой строки в dsCustomer, которую я должен пойти и проверить их значение в dsCategory.

Я попытался объединить две таблицы, но это работает, потому что dsCustomer должен поддерживать те же записи, только что добавил вычисляемый столбец, выбранный из dsCategory.

caused by: org.apache.spark.sql.AnalysisException: cannot resolve '`totalAmount`' given input columns: [categoryID,borne_min,borne_max];; 'Filter (('totalAmount>= borne_min#220) && ('totalAmount < borne_max#221))

1 Ответ

0 голосов
/ 22 мая 2019

Вы должны объединить два набора данных. withColumn разрешает модификации только одного и того же набора данных.

UPDATE

У меня не было времени, чтобы подробно объяснить, что я имею в виду. Это то, что я пытался объяснить. Вы можете присоединиться к двум фреймам данных. В вашем случае вам нужно левое соединение, чтобы сохранить строки, которые не имеют соответствующей категории.

from pyspark.sql import SparkSession


spark = SparkSession.builder.getOrCreate()

cust = [
    ('customer1', 'H1', 250), 
    ('customer2', 'H2', 175), 
    ('customer3', 'H3', 4000),
    ('customer4', 'H3', 9000)
]

cust_df = spark.createDataFrame(cust, ['customerID', 'idpt', 'totalAmount'])

cust_df.show()

cat = [
    ('A', 'H2', 0   , 1000),
    ('B', 'H2', 1000, 5000),
    ('C', 'H2', 5000, 7000),
    ('D', 'H2', 7000, 10000),
    ('F', 'H3', 0   , 1000),
    ('G', 'H3', 1000, 5000),
    ('H', 'H3', 5000, 7000),
    ('I', 'H3', 7000, 1000000)
]

cat_df = spark.createDataFrame(cat, ['categoryID', 'idpt', 'borne_min', 'borne_max'])

cat_df.show()

cust_df.join(cat_df, 
             (cust_df.idpt == cat_df.idpt) & 
             (cust_df.totalAmount >= cat_df.borne_min) & 
             (cust_df.totalAmount <= cat_df.borne_max)
            , how='left') \
.select(cust_df.customerID, cust_df.idpt, cust_df.totalAmount, cat_df.categoryID) \
.show()

выход

+----------+----+-----------+
|customerID|idpt|totalAmount|
+----------+----+-----------+
| customer1|  H1|        250|
| customer2|  H2|        175|
| customer3|  H3|       4000|
| customer4|  H3|       9000|
+----------+----+-----------+

+----------+----+---------+---------+
|categoryID|idpt|borne_min|borne_max|
+----------+----+---------+---------+
|         A|  H2|        0|     1000|
|         B|  H2|     1000|     5000|
|         C|  H2|     5000|     7000|
|         D|  H2|     7000|    10000|
|         F|  H3|        0|     1000|
|         G|  H3|     1000|     5000|
|         H|  H3|     5000|     7000|
|         I|  H3|     7000|  1000000|
+----------+----+---------+---------+

+----------+----+-----------+----------+
|customerID|idpt|totalAmount|categoryID|
+----------+----+-----------+----------+
| customer1|  H1|        250|      null|
| customer3|  H3|       4000|         G|
| customer4|  H3|       9000|         I|
| customer2|  H2|        175|         A|
+----------+----+-----------+----------+
...