BigQuery 上的图形预处理在 BigQuery 中使用带有结构体、字典类型的 for 循环 我在 Python3.8 中的解决方案你不必这样做只是一个参考

问题描述


更新

  • 我在 bigquery 中使用 for 循环 语句找到了解决方案,但是当存在多个 tag_id 时,它太慢且成本太高
  • 使用 join 语句而不是 for 循环语句是唯一的好方法(我仍然没有找到解决方案)

device_id有多个tag_id(如果tag_id相同,app_id也相同。)
tag_id 有多个 device_id

我想要这个示例表中的字典列表(大查询中的结构类型)(如 python 中的字典)

+-----------+--------+--------+
| device_id | tag_id | app_id |
+-----------+--------+--------+
| d1        | t1     | ai1    |
| d1        | t2     | ai2    |
| d3        | t3     | ai3    |
| d4        | t3     | ai3    |
| d5        | t2     | ai2    |
| d6        | t3     | ai3    |
+-----------+--------+--------+
  • 我想使用上表创建网络
  • [tag_id & tag_id] 只能使用 device_id 连接

上例表的正确输出

Output - Visualized Image

[{tag_id : [t1,t2],device_id : [d1,d5],app_id : [ai1,ai2]},{tag_id : [t3],device_id : [d3,d4,d6],app_id : [ai3]}]

结构是

List(Dictionary(list of tag_id,list of device_id,list of app_id))

我需要 BigQuery 解决方案,因为上面的示例表非常大。 (不允许使用 Spark 或 Python)

BigQuery UDF 也可以(任何人都可以将此解决方案转换为 javascript)

我在 python3.8 中的解决方案(你不必这样做。只是一个参考。)

  • 步骤 1. 制作具有唯一 device_id 列表的 tag_id 字典列表。 (我称之为“半节点”
def create_semi_node_list(raw_df):
    unique_tag_id_lst = raw_df['tag_id'].to_list()
    
    # create semi-node
    semi_node = []
    
    for tag_id in unique_tag_id_lst:
        # make tag_id,device_id bucket
        bucket = {}
        bucket['tag_id'] = [tag_id]
        bucket['device_id'] = df[df["tag_id"] == tag_id]["device_id"].to_list()
        bucket['app_id'] = list(set(df[df["tag_id"] == tag_id]["app_id"].to_list()))

        semi_node.append(bucket)
  • 第 2 步:使用 for 循环生成结果(我称之为 “主节点”
  1. 列表的一个字典值循环另一个字典值。(它的案例数是df长度的平方)
  2. list 的字典每个都有唯一的 tag_id(因为上面的函数)。
  3. 因此,如果它们具有相同的 device_id,则合并(并使用 for 循环字典值制作空字典)
def create_node_list(node_lst):
    semi_node = copy.deepcopy(node_lst)
    main_node_idx = 0
    comp_node_idx = 0
    result = []
    
    while True:
        key_length = len(semi_node)
        
        if main_node_idx == comp_node_idx:
            if main_node_idx+1 < key_length:
                comp_node_idx += 1
            else:
                break 

        elif comp_node_idx+1 == key_length:
            main_node_idx += 1
            comp_node_idx = 0

        elif (main_node_idx+1 < key_length) and (len(semi_node[main_node_idx]['tag_id']) == 0):
            main_node_idx += 1

        elif (comp_node_idx+1 < key_length) and (len(semi_node[comp_node_idx]['tag_id']) == 0):
            comp_node_idx += 1

        else:
            # if have same device_id
            var1 = len(semi_node[main_node_idx]['device_id'])
            var2 = len(semi_node[comp_node_idx]['device_id'])
            if var1 + var2 != len(set(semi_node[main_node_idx]['device_id'] + semi_node[comp_node_idx]['device_id'])):
                # merge device_id bucket
                
                result.extend(
                [{
                    'tag_id' : list(set(semi_node[main_node_idx]['tag_id'] + semi_node[comp_node_idx]['tag_id'])),'device_id' : list(set(semi_node[main_node_idx]['device_id'] + semi_node[comp_node_idx]['device_id'])),'app_id' : list(set(semi_node[main_node_idx]['app_id'] + semi_node[comp_node_idx]['app_id'])),'package_nm' : list(set(semi_node[main_node_idx]['package_nm'] + semi_node[comp_node_idx]['package_nm']))
                }]
                )
                    
                semi_node[comp_node_idx]['tag_id'] = []
  • 步骤 3. 删除具有空值的字典
def pop_empty_node(node_list):
    # node_list is main-node
    try:
        while True:
            empty_node_idx=node_list.index({"tag_id":[],"device_id":[],"app_id":[],"package_nm":[]})
            node_list.pop(empty_node_idx)
    except:
        return node_list

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...