Python代码阅读(第33篇):反转字典

Python59

本篇阅读的代码实现了将一个字典进行反转,且原字典的值非唯一。

collect_dictionary

def collect_dictionary(obj):
  inv_obj = {}
  for key, value in obj.items():
    inv_obj.setdefault(value, list()).append(key)
  return inv_obj

EXAMPLES
ages = {
  "Peter": 10,
  "Isabel": 10,
  "Anna": 9,
}
collect_dictionary(ages) # { 10: ["Peter", "Isabel"], 9: ["Anna"] }

collect_dictionary函数接收一个字典,返回反转后的字典。函数使用 dictionary.items()循环获取每一个原字典的键值对,使用 dictionary.setdefault()append()将原字典的值映射到键上。使用 list()将新键的值定义为列表。

因为原字典的所有值不唯一,反转字典之后,新的键也可能对应多个值。因此反转后的字典的值是一个列表,每个列表中的元素是原字典的一个或多个键。

dictionary. setdefault(key[, default])如果字典存在键 key,返回它的值。如果不存在,插入值为 default的键 key,并返回 default

for key, value in obj.items():
    inv_obj.setdefault(value, list()).append(key)

如果新的字典 inv_obj已经有 key == value,就会返回这个 key对应的值(一个列表),然后使用 append将原字典的键加入其中。如果新的字典 inv_obj没有 key == value,就会插入这个 key,设置它的值为 list(),并返回这个空列表。然后使用 append将原字典的键加入其中。

Original: https://www.cnblogs.com/felixz/p/15530409.html
Author: FelixZ
Title: Python代码阅读(第33篇):反转字典



相关阅读1

Title: Python使用ch-orm对ClickHouse简单查询及写入

前不久新项目中需要用到ClickHouse,作为一个合格的Python程序员,首先当然是找找有没有合适的轮子。

翻了一圈,infi.clickhouse_orm在功能和易用性上没有明显的短板,其ORM API对后端程序员格外亲切。可惜主分支已经八个月没有更新了,据闻核心开发者已离职,而infi.clickhouse_orm尚不支持一些我需要的新功能如Geo类型和函数,基于这些原因,这篇文章的主角ch-orm也就诞生了。

ch-orm库fork自infi.clickhouse_orm(v2.1.1)。

与infi相比,ch-orm支持同步和异步两种方式与ClickHouse服务器交互,它添加了一些新功能:

  • 异步支持(AioDatabase)
  • 为所有同步API提供async接口
  • 类型注解
  • 大部分对外API实现了类型注解
  • 新的类型支持
  • Tuple
  • Geo类型;Point、Ring等
  • 新的函数支持
  • Geo函数等
  • 支持创建临时表(TemporaryModel)
  • session会话

快速开始

通过pip安装ch-orm

pip install ch-orm

虽然pypi的库名为 ch-orm,但在代码中需要导入的是 clickhouse_orm

from clickhouse_orm import Database, Model, MergeTree
from clickhouse_orm.fields import (
    StringField, Int32Field, UUIDField, Int8Field
)
from clickhouse_orm.contrib.geo.fields import PointField

class Residence(Model):
    uuid = UUIDField()
    residence_type = Int8Field()
    geo = PointField(db_column='geo_wgs84')
    geohash_wgs84 = StringField()
    province = StringField()
    city = StringField()
    district = StringField()
    poi_id = Int32Field(default=1000)
    poi_name = StringField()
    p_geo_bd09 = PointField()

    engine = MergeTree(partition_key=('uuid', ), order_by=('uuid', ))

    @classmethod
    def table_name(cls):
        return 'residence'

上面定义了一个 Residence模型,它将会映射到ClickHouse上的 residence表,而 Residence中众多Field属性则被映射为表中的列,可以在Python中对Residence实例进行操作进而处理ClickHouse(没错,就像Django ORM所做的那样)

接下来,先假定此时 residence尚不存在,借助 Residence来创建它。

想要对数据库执行操作,首先必须实例化一个Database对象(或AioDatabase),可以粗浅的理解为它和数据库连接属于一类抽象,内部实现对后端数据库的交互。

from clickhouse_orm.database import Database
from clickhouse_orm.aio.database import AioDatabase

以同步方式创建数据库
sync_db = Database('db-test', db_url='http://localhost:8123/')
sync_db.create_table(Residence)

以异步方式创建数据库
async def main():
    async_db = AioDatabase('db-test', db_url='http://localhost:8123/')
    # 异步模型下需要主动执行init方法初始化
    await async_db.init()
    await async_db.create_table(Residence)

此时,db-test库内应当出现了一个名为 residence的表。

ClickHouse在数据写入性能表现十分优异,ch-orm能轻易处理写入数据需求

以写入100万条数据为例,使用生成器创建100万个Residence随机实例

import uuid

from clickhouse_orm.contrib.geo.fields import Point

同步写入100万条residence
sync_db.insert(
    (Residence(uuid=str(uuid.uuid4()), geo=Point(120, 20)) for _ in range(1000000)),
    batch_size=10000
)

异步写入100万条residence
async def insert():
    ...

    await async_db.insert(
        (Residence(uuid=str(uuid.uuid4()), geo=Point(120, 20)) for _ in range(1000000)),
        batch_size=10000
    )

示例中仅对 uuidgeo列进行赋值,其他字段会被设置为默认值(而非None值)

可以看看 residence表中有多少条数据

同步方式查询Residence行数
Residence.objects_in(sync_db).count()

异步方式查询Residence行数
async def read_count():
    ...

    await Residence.objects_in(async_db).count()

ch-orm实现了QuerySet,暴露API基本参照Django设计的,如前述的获取表行数的 count()方法就来自 QuerySet

与Django不同的是,ch-orm仅将QuerySet作为查询实例,不具备查询结果缓存功能,这代表如果对一个QuerySet对象执行两次迭代,与后端数据库的交互将变成两次而非一次。

可以通过Model的类方法 objects_in获得一个 QuerySet实例,接着来查询 uuid="48d75e4d-8e6f-4acd-a2e9-f4c3059b5b30"的数据

同步API
queryset = Residence.objects_in(sync_db)
queryset = queryset.filter(Residence.uuid == "48d75e4d-8e6f-4acd-a2e9-f4c3059b5b30")
result = list(queryset)

对于异步API
queryset = Residence.objects_in(async_db)
queryset = queryset.filter(Residence.uuid == "48d75e4d-8e6f-4acd-a2e9-f4c3059b5b30")
result = [_ async for _ in queryset]

真正的查询请求是在对queryset迭代时处理的,因此下列两行代码不会与数据库后端进行交互

queryset = Residence.objects_in(sync_db)
queryset = queryset.filter(Residence.uuid == "48d75e4d-8e6f-4acd-a2e9-f4c3059b5b30")

最终得到一个由Residence实例的组成的结果列表result。

ch-orm具备日常使用的大多数场景功能

这些内容Github仓库有相应的文档,限于本文篇幅这里就不再过多介绍。

Original: https://www.cnblogs.com/lazyfish007/p/16343124.html
Author: 秋叶红了
Title: Python使用ch-orm对ClickHouse简单查询及写入

相关阅读2

Title: 使用Python探索四大名著【红楼梦】人物之间的关系,简直帅呆了

Python代码阅读(第33篇):反转字典

《红楼梦》作为我国四大名著之一,古典小说的巅峰之作,粉丝量极其庞大,而红学也经久不衰。所以我们今天通过 Python 来探索下红楼梦里那千丝万缕的人物关系,话不多说,开始整活!

; 一、准备工作

  • 红楼梦txt格式电子书一份
  • 金陵十二钗+贾宝玉人物名称列表
宝玉 nr
黛玉 nr
宝钗 nr
湘云 nr
凤姐 nr
李纨 nr
元春 nr
迎春 nr
探春 nr
惜春 nr
妙玉 nr
巧姐 nr
秦氏 nr

该分列表是为了做分词时使用,后面的 nr 就是人名的意思。

二、人物出镜次数

首先读取小说

with open("红楼梦.txt", encoding="gb18030") as f:
    honglou = f.read()

# 更多视频教程、电子书、源码加君羊:279199867

接下来进行出场次数数据整理

honglou = honglou.replace("\n", " ")
honglou_new = honglou.split(" ")
renwu_list = ['宝玉', '黛玉', '宝钗', '湘云', '凤姐', '李纨', '元春', '迎春', '探春', '惜春', '妙玉', '巧姐', '秦氏']
renwu = pd.DataFrame(data=renwu_list, columns=['姓名'])
renwu['出现次数'] = renwu.apply(lambda x: len([k for k in honglou_new if x[u'姓名'] in k]), axis=1)
renwu.to_csv('renwu.csv', index=False, sep=',')
renwu.sort_values('出现次数', ascending=False, inplace=True)
attr = renwu['姓名'][0:12]
v1 = renwu['出现次数'][0:12]

这样我们就得到了 attr 和 v1 两个数据,内容如下

Python代码阅读(第33篇):反转字典

下面就可以通过 pyecharts 来绘制柱状图了

bar = (
    Bar()
    .add_xaxis(attr.tolist())
    .add_yaxis("上镜次数", v1.tolist())
    .set_global_opts(title_opts=opts.TitleOpts(title="红楼梦上镜13人"))
)
bar.render_notebook()

三、人物关系

1、数据处理

我们先将读取到内存中的小说内容进行 jieba 分词处理

import jieba
jieba.load_userdict("renwu_forcut")
renwu_data = pd.read_csv("renwu_forcut", header=-1)
mylist = [k[0].split(" ")[0] for k in renwu_data.values.tolist()]

通过 load_userdict 将我们上面自定义的词典加载到了 jieba 库中

分词处理

tmpNames = []
names = {}
relationships = {}
for h in honglou:
    h.replace("贾妃", "元春")
    h.replace("李宫裁", "李纨")
    poss = pseg.cut(h)
    tmpNames.append([])
    for w in poss:
        if w.flag != 'nr' or len(w.word) != 2 or w.word not in mylist:
            continue
        tmpNames[-1].append(w.word)
        if names.get(w.word) is None:
            names[w.word] = 0
        relationships[w.word] = {}
        names[w.word] += 1

因为文中"贾妃", "元春","李宫裁", "李纨" 等人物名字混用严重,所以这里做替换处理。

然后使用 jieba 库提供的 pseg 工具来做分词处理,会返回每个分词的词性。

之后做判断,只有符合要求且在我们提供的字典列表里的分词,才会保留。

一个人每出现一次,就会增加一,方便后面画关系图时,人物 node 大小的确定。

对于存在于我们自定义词典的人名,保存到一个临时变量当中 tmpNames

处理每个段落中的人物关系

for name in tmpNames:
        for name1 in name:
            for name2 in name:
                if name1 == name2:
                    continue
                if relationships[name1].get(name2) is None:
                    relationships[name1][name2] = 1
                else:
                    relationships[name1][name2] += 1

对于出现在同一个段落中的人物,我们认为他们是关系紧密的,同时每出现一次,关系增加1 。

可以把相关信息保存到文件当中

with open("relationship.csv", "w", encoding='utf-8') as f:
        f.write("Source,Target,Weight\n")
        for name, edges in relationships.items():
            for v, w in edges.items():
                f.write(name + "," + v + "," + str(w) + "\n")
with open("NameNode.csv", "w", encoding='utf-8') as f:
    f.write("ID,Label,Weight\n")
    for name, times in names.items():
        f.write(name + "," + name + "," + str(times) + "\n")

文件1:人物关系表,包含首先出现的人物、之后出现的人物和一同出现次数。

文件2:人物比重表,包含该人物总体出现次数,出现次数越多,认为所占比重越大。

2、数据分析

下面我们可以做一些简单的人物关系分析

这里我们还是使用 pyecharts 绘制图表

def deal_graph():
    relationship_data = pd.read_csv('relationship.csv')
    namenode_data = pd.read_csv('NameNode.csv')
    relationship_data_list = relationship_data.values.tolist()
    namenode_data_list = namenode_data.values.tolist()
    nodes = []
    for node in namenode_data_list:
        if node[0] == "宝玉":
            node[2] = node[2]/3
        nodes.append({"name": node[0], "symbolSize": node[2]/30})
    links = []
    for link in relationship_data_list:
        links.append({"source": link[0], "target": link[1], "value": link[2]})
    g = (
        Graph()
        .add("", nodes, links, repulsion=8000)
        .set_global_opts(title_opts=opts.TitleOpts(title="红楼人物关系"))
    )
    return g

首先把两个文件通过 pandas 读取到内存当中

对于"宝玉",由于其占比过大,如果统一进行缩放,会导致其他人物的 node 过小,展示不美观,所以这里先做了一次缩放

最后我们得到的人物关系图如下

Python代码阅读(第33篇):反转字典

铁子们,今天的分享就到这, 如果感觉文章内容不错的话,记得关注+收藏让更多的人看到!

给大家分享一套视频,非常全面!

Python爬虫:代码总是学完就忘记?100个爬虫实战项目!让你沉迷学习丨学以致用丨下一个Python大神就是你!

Original: https://www.cnblogs.com/hahaa/p/16576636.html
Author: 轻松学Python
Title: 使用Python探索四大名著【红楼梦】人物之间的关系,简直帅呆了

相关阅读3

Title: Python:SyntaxError:(unicode error) 'unicodeescape' codec can't decode bytes in pos

阅文时长

| 0.7分钟
字数统计

| 1123.2字符
主要内容

| 1、引言&背景 2、解决方案 3、声明与参考资料
『Python:SyntaxError:(unicode error) 'unicodeescape' codec can't decode bytes in pos』 编写人

| SCscHero
编写时间

| 2022/1/10 PM8:8
文章类型

| 系列
完成度

| 已完成
座右铭

每一个伟大的事业,都有一个微不足道的开始。

一、引言&背景 完成度:100%

a) 应对问题

Python报错如下如图:

......

Traceback (most recent call last):
File "C:\LIST.ENV\env.006.Python_ALL\64bit_3.9.6\lib\runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\LIST.ENV\env.006.Python_ALL\64bit_3.9.6\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "c:\Users\shaoczha\.vscode\extensions\ms-python.python-2021.8.1159798656\pythonFiles\lib\python\debugpy\__main__.py", line 45, in
cli.main()
File "c:\Users\shaoczha\.vscode\extensions\ms-python.python-2021.8.1159798656\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 444, in main
run()
File "c:\Users\shaoczha\.vscode\extensions\ms-python.python-2021.8.1159798656\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 285, in run_file
runpy.run_path(target_as_str, run_name=compat.force_str("__main__"))
File "C:\LIST.ENV\env.006.Python_ALL\64bit_3.9.6\lib\runpy.py", line 267, in run_path
code, fname = _get_code_from_file(run_name, path_name)
File "C:\LIST.ENV\env.006.Python_ALL\64bit_3.9.6\lib\runpy.py", line 242, in _get_code_from_file
code = compile(f.read(), fname, 'exec')
File "XXXXXXXXXXXXXXXXXXXXXXXX.py", line 255
save_variable(X_train,'C:\LIST.MeGitCloud List\x.txt')
^
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 23-24: truncated \xXX escape

b) 应用场景

  • py脚本字符解析报错。

二、解决方案 完成度:100%

此类异常通常是由于特殊字符造成的,无法解析,因此遇见此种报错检查下特殊字符。本人的问题是没有按照Linux的路径斜杠符号/来写路径,而是按照Windows的路径斜杠符号\来写的,因此造成了这个异常。

三、声明与参考资料 完成度:100%

原创博文,未经许可请勿转载。

如有帮助,欢迎点赞、收藏、关注。如有问题,请评论留言!如需与博主联系的,直接博客私信SCscHero即可。

Original: https://www.cnblogs.com/SCscHero/p/15790123.html
Author: SCscHero
Title: Python:SyntaxError:(unicode error) 'unicodeescape' codec can't decode bytes in pos