不懂就问,我有一个题库的字典,获取某一个题目时(id),使用 for 循环和 pandas 效率是差不多了的,没有提升。

2021-01-19 09:20:18 +08:00
 rationa1cuzz
题库字典大概是{一级标题:{
二级标题:{
sublist:[{id:1,
题目:xx,
答案:xx}]
}
}
}
总的题目大概有 12k 条,实际字段要比这个多一些,但是结构一样

语言 python,或者说有没有其他更好的方法
2503 次点击
所在节点    Python
14 条回复
wuwukai007
2021-01-19 09:27:11 +08:00
pandas 加索引了吗
xpresslink
2021-01-19 09:35:20 +08:00
没有。
你的题目是存放在第三级的 list 中的,只能顺序查找。
除非你自己再建立一套以题目 id 为 key 的索引字典。
或者干脆牺牲空间,直接把题目改成一级字典,每个题目 id 当成 key 一个,一级和二级标题当成每个题目的两个属性。
ClutchBear
2021-01-19 09:39:35 +08:00
用 mysql 或者 es 呗
sznewbee096
2021-01-19 10:23:46 +08:00
建议把数据放在数据库,为以后扩容、转移,快速加载准备
princelai
2021-01-19 11:15:10 +08:00
我试了试,只能循环转为 dataframe,之后查询就会快很多

```
d = {
'中学': {
'初一': {
'数学': [{
'id': 1,
'题目': 'xx',
'答案': 'xx'
},
{
'id': 2,
'题目': 'xx',
'答案': 'xx'
}
]
},
'初三': {
'语文': [{
'id': 3,
'题目': 'xx',
'答案': 'xx'
},
{
'id': 4,
'题目': 'xx',
'答案': 'xx'
}
]
}
},
'小学': {
'三年级': {
'英语': [{
'id': 5,
'题目': 'xx',
'答案': 'xx'
},
{
'id': 6,
'题目': 'xx',
'答案': 'xx'
}
],
'体育': [{
'id': 7,
'题目': 'xx',
'答案': 'xx'
},
{
'id': 8,
'题目': 'xx',
'答案': 'xx'
}
]
},
'五年级': {
'美术': [{
'id': 9,
'题目': 'xx',
'答案': 'xx'
},
{
'id': 10,
'题目': 'xx',
'答案': 'xx'
}
]
}
}
}

trans = []

for title1_key,title1_val in d.items():
for title2_key,title2_val in title1_val.items():
for title3_key, title3_val in title2_val.items():
tmp_df = pd.DataFrame(title3_val)
tmp_df['title1'] = title1_key
tmp_df['title2'] = title2_key
tmp_df['title3'] = title3_key
trans.append(tmp_df)
df = pd.concat(trans)
```

查询的话,大数据量用 query 方法会更快一点

df.query('id==5')
Out[156]:
id 题目 答案 title1 title2 title3
0 5 xx xx 小学 三年级 英语

df.query("title2=='三年级' and title3=='英语'").id
Out[158]:
0 5
1 6
ijustdo
2021-01-19 12:27:33 +08:00
加索引的思路没错

doc_inx = {123: {'ft': '一年级', 'st': '语文', 'inx': 5}, 321: {'ft': '二年级', 'st': '数学', 'inx': 5}}
建立这样的索引
获取的时候
index_obj = doc_inx[321]
result = 题库字典[index_obj['ft']][index_obj['st']]['sublist'][index_obj['inx']]
imn1
2021-01-19 12:50:40 +08:00
好奇你的 pandas 是什么结构?
rationa1cuzz
2021-01-19 13:53:38 +08:00
@princelai 跟你类似的构造结构取值不同,换了 query 查询结果感觉提升也不是很明显,12k 的数据,for 循环取值大概 1.8s pandas 1.2s 不知道正不正常,没有加索引
rationa1cuzz
2021-01-19 13:54:13 +08:00
@ijustdo 我试试
rationa1cuzz
2021-01-19 14:06:48 +08:00
这里 for 也是 1.2s 不是 1.8s
princelai
2021-01-19 14:07:14 +08:00
@rationa1cuzz #8 我自己手上正好有一个 12k 的数据集

data.shape
Out[8]: (116419, 12)

%timeit data.query("startCityId==321 and endCityId==3401")
3.14 ms ± 147 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit data.query("startCityId==321 and endCityId==3401 and carType=='8_1'")
12.5 ms ± 7.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

data.startCityId.nunique()
Out[10]: 265
data.endCityId.nunique()
Out[11]: 284

carType 是一个字符串,另两个是整数类型,这么小的数据集查询这么慢,肯定是哪里出问题了
rationa1cuzz
2021-01-19 14:20:21 +08:00
@princelai 我这个地方看的是接口响应时间并没有去看实际的查询时间,而且经过大量测试发现 for 循环去查找时间竟然比使用 pandas 还要短,我想应该是我哪里出了问题。
princelai
2021-01-19 14:37:28 +08:00
我用你这样的结构生成了一个 15 万的数据
```
import pandas as pd
from random import randint, choices

opt_t1 = {'小学': ['一年级', '二年级', '三年级', '四年级', '五年级', '六年级'],
'初中': ['初一', '初二', '初三'],
'高中': ['高一', '高二', '高三'],
'大学': ['大一', '大二', '大三', '大四']}

opt_t2 = ['数学', '语文', '英语', '计算机']

t1_list = []
for k in opt_t1.keys():
i = randint(30000, 50000)
tmp = pd.DataFrame({'title2': choices(opt_t1.get(k), k=i), 'title3': choices(opt_t2, k=i)})
tmp['title1'] = k
tmp['题目'] = 'xx'
tmp['答案'] = 'xxx'
t1_list.append(tmp)
df = pd.concat(t1_list)
df['id_num'] = range(1, df.shape[0]+1)
df = df.sample(frac=1)
df.index = range(df.shape[0])


```

结果如下

%timeit df.query("title2=='大二' and title3=='计算机'")
12.5 ms ± 7.16 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

你这秒级接口通常是在里面处理数据或者有 io 吧
rationa1cuzz
2021-01-19 15:10:52 +08:00
@princelai 是我的问题,因为这个接口响应时间很慢,第一反应就是查询除了问题,所以没考虑到,我再次看了一下查询时间,随机取了终端几个 id 查找,发现 for 循环大概是 3ms pandas 是 70ms,这个是正常的吗

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/746148

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX