Как определить повторные вхождения строкового столбца в Hive? - PullRequest
1 голос
/ 25 марта 2019

У меня есть такой вид в Улей:

id        sequencenumber          appname
242539622              1          A
242539622              2          A
242539622              3          A
242539622              4          B
242539622              5          B
242539622              6          C
242539622              7          D
242539622              8          D
242539622              9          D
242539622             10          B
242539622             11          B
242539622             12          D
242539622             13          D
242539622             14          F 

Я хотел бы иметь для каждого идентификатора следующий вид:

id        sequencenumber          appname    appname_c
242539622              1          A             A
242539622              2          A             A
242539622              3          A             A
242539622              4          B             B_1
242539622              5          B             B_1
242539622              6          C             C
242539622              7          D             D_1
242539622              8          D             D_1
242539622              9          D             D_1
242539622             10          B             B_2
242539622             11          B             B_2
242539622             12          D             D_2
242539622             13          D             D_2
242539622             14          F             F 

Или что-то близкое к этому, которое может идентифицировать повторение данного события в последовательности.

Моя конечная цель - рассчитать время, проведенное в каждой группе событий (или указать состояние, если хотите, в контексте моделирования Маркова) с учетом наличия обратной связи. Например, время, проведенное в B_1 в вышеприведенном примере, можно сравнить с B_2.

Поиск оконных функций в Hive ( link ), но я думаю, что они не могут проводить сравнения строк, как это делает R / Python.

Ответы [ 2 ]

2 голосов
/ 25 марта 2019

Решение с использованием оконных функций Hive.Я использовал ваши данные, чтобы проверить это, удалить your_table CTE и использовать вашу таблицу вместо этого.Результат, как и ожидалось.

with your_table as (--remove this CTE, use your table instead
select stack(14,
'242539622', 1,'A',
'242539622', 2,'A',
'242539622', 3,'A',
'242539622', 4,'B',
'242539622', 5,'B',
'242539622', 6,'C',
'242539622', 7,'D',
'242539622', 8,'D',
'242539622', 9,'D',
'242539622',10,'B',
'242539622',11,'B',
'242539622',12,'D',
'242539622',13,'D',
'242539622',14,'F'
) as (id,sequencenumber,appname)
) --remove this CTE, use your table instead

select id,sequencenumber,appname, 
       case when sum(new_grp_flag) over(partition by id, group_name) = 1 then appname --only one group of consequent runs exists (like A)
            else        
            nvl(concat(group_name, '_', 
                       sum(new_grp_flag) over(partition by id, group_name order by sequencenumber) --rolling sum of new_group_flag
                       ),appname) 
        end appname_c       
from
(       

select id,sequencenumber,appname,
       case when appname=prev_appname or appname=next_appname then appname end group_name, --identify group of the same app
       case when appname<>prev_appname or prev_appname is null then 1 end new_grp_flag     --one 1 per each group
from       
(
select id,sequencenumber,appname,
       lag(appname)  over(partition by id order by sequencenumber) prev_appname, --need these columns
       lead(appname) over(partition by id order by sequencenumber) next_appname  --to identify groups of records w same app
from your_table --replace with your table
)s
)s
order by id,sequencenumber
;

Результат:

OK
id        sequencenumber     appname    appname_c
242539622       1       A       A
242539622       2       A       A
242539622       3       A       A
242539622       4       B       B_1
242539622       5       B       B_1
242539622       6       C       C
242539622       7       D       D_1
242539622       8       D       D_1
242539622       9       D       D_1
242539622       10      B       B_2
242539622       11      B       B_2
242539622       12      D       D_2
242539622       13      D       D_2
242539622       14      F       F
Time taken: 232.319 seconds, Fetched: 14 row(s)
1 голос
/ 25 марта 2019

Вам нужно выполнить 2 оконные функции для достижения этого результата.

Используя pyspark и предполагая, что df - ваш фрейм данных:

from pyspark.sql import functions as F, Window

df.withColumn(
    "fg",
    F.lag("appname").over(Window.partitionBy("id").orderBy("sequencenumber)
).withColumn(
    "fg",
    F.when(
        F.col("fg")==F.col("id"),
        0
    ).otherwise(1)
).withColumn(
    "fg",
    F.sum("fg").over(Window.partitionBy("id", "appname"))
).show()
...