如何解决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 连接
上例表的正确输出是
[{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 循环生成结果(我称之为 “主节点”)
- 列表的一个字典值循环另一个字典值。(它的案例数是df长度的平方)
- list 的字典每个都有唯一的 tag_id(因为上面的函数)。
- 因此,如果它们具有相同的 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 举报,一经查实,本站将立刻删除。