如何识别 Hive 中重复出现的字符串列?

Posted

技术标签:

【中文标题】如何识别 Hive 中重复出现的字符串列?【英文标题】:How to identify repeated occurrences of a string column in Hive? 【发布时间】:2019-03-24 23:49:49 【问题描述】:

我在 Hive 中有这样的视图:

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 都有以下视图:

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 那样进行逐行比较。

【问题讨论】:

【参考方案1】:

使用 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)

【讨论】:

谢谢@leftjoin 这正是我想要的。【参考方案2】:

您需要执行 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()

【讨论】:

感谢 Steven,但这不会产生预期的结果。

以上是关于如何识别 Hive 中重复出现的字符串列?的主要内容,如果未能解决你的问题,请参考以下文章

Hive:字符串中的第一次和最后一次出现

按字符串列的长度对数据帧进行排序[重复]

如何在 Ms Access 2007 中使用 MySQL 视图,而不会出现字符串列的垃圾?

显示字符串列以特定字母开头的行[重复]

从pandas DataFrame中另一列中的位置给定的字符串列中提取字符[重复]

通过熊猫中的字符串列聚合数据框[重复]