Squeak.ru - шаблоны программирования

Spark: как создать идентификатор сеанса на основе идентификатора пользователя и отметки времени

Извините за вопрос новичка.

В настоящее время у меня есть файлы журналов, которые содержат такие поля, как: userId, event и timestamp, но не имеют идентификатора sessionId. Моя цель — создать sessionId для каждой записи на основе метки времени и предопределенного значения TIMEOUT.

Если значение TIMEOUT равно 10, а образец DataFrame:

scala> eventSequence.show(false)

  +----------+------------+----------+ 
  |uerId     |event       |timestamp |
  +----------+------------+----------+ 
  |U1        |A           |1         | 
  |U2        |B           |2         |
  |U1        |C           |5         |
  |U3        |A           |8         |
  |U1        |D           |20        |
  |U2        |B           |23        |
  +----------+------------+----------+

Цель:

  +----------+------------+----------+----------+
  |uerId     |event       |timestamp |sessionId |
  +----------+------------+----------+----------+
  |U1        |A           |1         |S1        |
  |U2        |B           |2         |S2        |
  |U1        |C           |5         |S1        |
  |U3        |A           |8         |S3        |
  |U1        |D           |20        |S4        |
  |U2        |B           |23        |S5        |
  +----------+------------+----------+----------+

Я нашел одно решение в R (Создайте идентификатор сеанса на основе userID и различия в timeStamp), а в Spark я не могу разобраться.

Спасибо за любые предложения по этой проблеме.



Ответы:


1

Ответ Шона касается «Как создать новый столбец», а моя цель - «Как создать столбец sessionId на основе метки времени». После нескольких дней борьбы функция Window применяется в этом сценарии как простое решение.

Окно введено со Spark 1.4, оно предоставляет функции, когда такие операции необходимы:

оба работают с группой строк, возвращая одно значение для каждой входной строки.

Чтобы создать идентификатор сеанса на основе метки времени, сначала мне нужно получить разницу между двумя непосредственными операциями пользователя А. windowDef определяет, что окно будет разделено по «userId» и упорядочено по отметке времени, тогда diff — это столбец, который будет возвращать значение для каждой строки, значение которого будет 1 строкой после текущей строки в разделе (группе) или null если текущая строка является последней строкой в ​​этом разделе

def handleDiff(timeOut: Int) = {
  udf {(timeDiff: Int, timestamp: Int) => if(timeDiff > timeOut) timestamp + ";" else timestamp + ""}
}
val windowDef = Window.partitionBy("userId").orderBy("timestamp")
val diff: Column = lead(eventSequence("timestamp"), 1).over(windowDef)
val dfTSDiff = eventSequence.
withColumn("time_diff", diff - eventSequence("timestamp")).
withColumn("event_seq", handleDiff(TIME_OUT)(col("time_diff"), col("timestamp"))).
groupBy("userId").agg(GroupConcat(col("event_seq")).alias("event_seqs"))

Обновлено: затем используйте функцию Window, чтобы применить операцию, подобную "cumsum" (предусмотренную в Pandas):

// Define a Window, partitioned by userId (partitionBy), ordered by timestamp (orderBy), and delivers all rows before current row in this partition as frame (rowsBetween)
val windowSpec = Window.partitionBy("userId").orderBy("timestamp").rowsBetween(Long.MinValue, 0)
val sessionDf = dfTSDiff.
  withColumn("ts_diff_flag", genTSFlag(TIME_OUT)(col("time_diff"))).
  select(col("userId"), col("eventSeq"), col("timestamp"), sum("ts_diff_flag").over(windowSpec).alias("sessionInteger")).
  withColumn("sessionId", genSessionId(col("userId"), col("sessionInteger")))

Ранее: затем разделить на ";" и получить каждый сеанс, создать sessionId; затем разбивается на «,» и взрывается до конечного результата. Таким образом, sessionId создается с помощью строковых операций. (Эта часть должна быть заменена операцией кумулятивной суммы, однако я не нашел хорошего решения)

Приветствуются любые идеи или мысли по этому вопросу.


GroupConcat можно найти здесь: замена SPARK SQL для агрегатной функции mysql GROUP_CONCAT

Ссылка: введение в блоки данных

07.01.2016

2

dt.withColumn('sessionId', expression for the new column sessionId)
например:
dt.timestamp + предопределенное значение TIMEOUT

31.12.2015
Новые материалы

Угловая структура архитектуры
Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

«Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

Создайте API с помощью Python FastAPI
Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

Веселье с прокси-сервером JavaScript
Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...