代碼在上次的基礎上做了一點優化,之前對項目要的最終結果了解有些偏差:
原始資料的那一列行業編碼是存在三位數和四位數的,我上次了解的三位數就是分割成兩位數進行查找,其實三位數的編碼是由于第一位的0沒有顯示,
是以例如311的編碼其實應該是0311,是以代碼進行了修改,對于三位數需要在開頭的位置補一個0,成為四位數再進行查找。
把三個方法的參數做了優化,擷取json字元串的方法隻需要一個參數(國标檔案),擷取單個結果的方法需要兩個參數(待查字元串,國标檔案),
擷取整個檔案需要三個參數(原始資料檔案,建立檔案,國标檔案)這個方法原始資料檔案每一行的編碼的周遊+使用國标檔案調用擷取json的方法一個個獲得結果。
最終結果圖:
源代碼:
1 import pandas as pd
2 import xlwt
3
4 """
5 rank的一系列變量是生成json字元串需要的标志
6 由于json結構是循環周遊生成的,是以在每一層都要留下标記,以便于下一層的建構
7 """
8
9 rank10="" #A 門類編号
10 rank11="" #A 門類名字
11 rank20="" #01 大類編号
12 rank21="" # 大類名字
13 rank30="" #012 中類編号
14 rank31="" # 中類名字
15 rank40="" #0121小類編号
16 rank41="" # 小類名字
17
18 """
19 ------------------------------------------------------------------------------------------------------------------------
20 """
21
22 def get_json(stdfilepwd):
23 """
24 :param stdfilepwd:标準國标檔案
25 :return: 标準行業次元json
26 """
27 """
28 filepwd 國标檔案格式
29 A 農、林、牧、漁業
30 A 農、林、牧、漁業
31 01 農業
32 011 谷物種植
33 0111 稻谷種植
34 0112 小麥種植
35 0113 玉米種植
36 """
37 # dict={"A":{"01":{"011":"谷物種植","0111":"稻谷種植"} ,
38 # "02":{"021":"林木育種和育苗","0211":"林木育種"}},
39 #
40 # "B":{"06":{ "0610":"煙煤和無煙煤開采洗選","0620":"褐煤開采洗選"},
41 # "07":{"0710":"石油開采","0720":"天然氣開采"}}
42 # }
43 # layer1=dict['A']
44 # print("第一層 A:\n",layer1)
45 #
46 # layer2 = dict['A']['01']
47 # print("第二層 01農業:\n", layer2)
48 #
49 # layer3 = dict['A']['01']["011"]
50 # print("第三層 :\n", layer3)
51 #讀取标準檔案 df預設不讀取第一行資料
52 df = pd.read_excel(stdfilepwd)
53 #首先尋找第一層大寫字母層的資料 定位行loc[] 定位
54 # print(df.columns.values[0]) #A
55
56 my_dict={"A":{}} #最終生成的字典
57 new_dict={"A":
58 {"農、林、牧、漁業":
59 {"01":
60 {"農業":
61 {"001":
62 {"谷物種植":
63 {
64 "0111":"稻谷種植","0112":"小麥種植"
65 }
66 }
67 }
68 }
69 }
70 }
71 }
72 # new_dict["A"].update(
73 # {df.loc[0].values[0]:df.loc[0].values[1]}
74 # )
75 # print("excel表的行數:\n",len(df.index.values))
76 # print("測試字典:\n",new_dict)
77 # print(df.loc[80].values)
78 # print("一個單元格資料的資料類型:\n",type(df.loc[0].values[0]))
79
80 #測試完畢 開始建構行業領域分類字典
81 #開始周遊表格 0 - 1423
82 for i in range(len(df.index.values)):
83 #由于表格的第一列資料的數字被判定為int型 是以要轉化成str
84 temp=df.loc[i].values
85 #轉化字元串 為了保險起見 兩列統一化處理 均轉化為字元串
86 # one 就是編碼 two就是編碼對應的行業名稱
87 one = str(temp[0])
88 # print(len(one))
89 two = str(temp[1])
90 # print("資料格式:\n",type(temp[0]))
91 #通過判斷values[0](數字編碼)的字元串的長度判斷處于字典的哪一層 如果長度是1 那麼在第一層門類 如果長度是2那麼在第二層大類 如果長度是3那麼在第三層中類
92 if(len(one)==1):
93 #rank10儲存編碼 rank11儲存行業名稱 後面類似
94 global rank10
95 global rank11
96 rank10=one
97 rank11=two
98 my_dict.update({rank10:{rank11:{}}})
99 if(len(one)==2):
100 global rank20
101 global rank21
102 rank20 = one
103 rank21 = two
104 my_dict[rank10][rank11].update({rank20:{rank21:{}}})
105 if (len(one) == 3):
106 global rank30
107 global rank31
108 rank30 = one
109 rank31 = two
110 #雖然會出現21 , 2111 中間沒有210的情況出現 但是可以優先生成所有的中類三位數的json結構 這一層會保留最後一個三位數中類 可以在後面進行判斷
111 my_dict[rank10][rank11][rank20][rank21].update({rank30:{rank31:{}}})
112 #這裡做了代碼的前三位字元串切分,為了判斷一下有沒有小類跳過中類的情況,需要直接跨過中類存儲,少了一層字典{}
113 if (len(one) == 4):
114 global rank40
115 global rank41
116 rank40 = one
117 rank41 = two
118 #把編碼分片 隻取前三位 然後和距離這個編碼最近的那個三位數中類做比較 如果相同則可以放到該中類的下一層字典 如果不同則該四位編碼自成一個字典
119 divide_rank40=rank40[:3]
120 # print(divide_rank40,rank30)
121 #判等
122 if(divide_rank40==rank30):
123 # print("!!!!!~~~~~~~~~~~~")
124 #相等 -> 放入該中類的下一層字典
125 my_dict[rank10][rank11][rank20][rank21][rank30][rank31].update({rank40:rank41})
126 else:
127 #不等 -> 自己成為一個字典 在大類裡直接自成一個字典
128 my_dict[rank10][rank11][rank20][rank21].update({rank40: rank41})
129 #得到最終的字典my_dict
130 # print(my_dict.keys())
131 # print(my_dict)
132 return my_dict
133 """
134 最終生成的json檔案
135
136 'A': {
137 '農、林、牧、漁業': {
138 '01': {
139 '農業': {
140 '011': {
141 '谷物種植': {
142 '0111': '稻谷種植',
143 '0112': '小麥種植',
144 '0113': '玉米種植',
145 '0119': '其他谷物種植'
146 }
147 },
148 '012': {
149 '豆類、油料和薯類種植': {
150 '0121': '豆類種植',
151 '0122': '油料種植',
152 '0123': '薯類種植'
153 }
154 },
155 '013': {
156 '棉、麻、糖、煙草種植': {
157 '0131': '棉花種植',
158 '0132': '麻類種植',
159 '0133': '糖料種植',
160 '0134': '煙草種植'
161 }
162 },
163 '014': {
164
165 """
166
167
168 """
169 ------------------------------------------------------------------------------------------------------------------------
170 """
171
172 def ger_stdstr(qb03,stdfilepwd):
173 """
174 :param qb03,stdfilepwd:
175 :return: str 标準行業次元字元串 行業代碼·門類名稱·大類名稱·中類名稱·小類名稱
176 qb03,待查編碼
177 stdfilepwd,标準國标檔案
178 """
179 #設定個标記,初始值False 說明預設找不到這個編碼 如果找到了則設為True 如果最終是False則重新分割字元串,回調函數
180 flag = False
181 #擷取字典
182 my_dict={}
183 my_dict.update(get_json(stdfilepwd))
184 # print(my_dict)
185
186 category="" #門類 名字
187
188 big_class="" #大類 名字
189
190 medium_class="" #中類 名字
191
192 small_class="" #小類 名字
193 # for 周遊第一層 門類
194 for items in my_dict.items():
195 res = "" # 定義該方法最終要傳回的标準化行業次元字元串
196 # print(items[0]) #ABCD
197 for layer_0 in items[1].items(): #這個for循環已經進入了 第一層 {} 裡面格式是 (門類名稱:{ })
198 # print("門類:\n",layer_0)
199 # print("門類名稱:\n",layer_0[0])
200 category=layer_0[0] #門類名稱[0]
201 """
202 -------------------------------------------------------------------
203 """
204 # 周遊第二層大類
205 """
206 每進入一層周遊,第一個for循環是進入一個這樣格式的資料 ( 編碼:{ } ) [0]是名稱 [1]是字典
207 之後第二個for循環進入那個字典{ }
208 字典建構的方式是 上一層是key 下一層是對應的value 同時它作為下一層的key
209 """
210 for layer_10 in layer_0[1].items():
211 # print("大類編碼(兩位):\n",layer_10[0])
212 #進入A對應的{ }
213 for layer_11 in layer_10[1].items(): #這個for循環已經進入了 第二層 {} 裡面格式是 (大類名稱:{ })
214 # print("大類:\n",layer_11)
215 big_class = layer_11[0]
216 # print("大類名稱:\n",big_class)
217 """
218 ---------------------------------------
219 """
220 #進入大類(01,{ })
221 for layer_20 in layer_11[1].items():#這個for循環已經進入了 第三層 {} 裡面格式是 (中類名稱:{ })或者不正常的跨過中類的四位編碼
222 # 這個分支的意思是有的類别隻到了大類,沒有經過中類直接分到了四位數的小類,是以必須分開周遊
223 #判斷第二層下一級的編碼是三位還是四位,如果是三位那麼是正常的中類劃分,如果是四位,那麼是跳過了中類劃分到了小類
224 if(len(layer_20[0])==4):
225 small_class=layer_20[1]
226 # print("大類直接分到小類:\n",small_class)
227 #判斷字元串
228 if(qb03==layer_20[0]):
229 print("跨過中類的小類,判斷成功!",qb03)
230 flag=True
231 res = items[0]+ qb03+ "·"+ category + "·" + big_class + "·"+small_class
232 return res
233 else:
234 for layer_21 in layer_20[1].items(): #這個for循環已經進入了 第三層正常的中類 {} 裡面格式是 (中類名稱:{ })
235 # print("中類:\n",layer_21)
236 medium_class = layer_21[0]
237 # print("中類名稱:\n",medium_class)
238 # 這裡是個大坑,我的周遊是進入值的那一層,編碼在上一級的周遊 layer_20[0]
239 # if (qb03 == layer_20[0]):
240 # print("三位中類判斷成功!", qb03)
241 # flag=True
242 # res = qb03 + "·" + category + "·" + big_class + "·" + medium_class
243 # return res
244 #繼續劃分到小類
245 for layer_30 in layer_21[1].items(): #這個for循環已經進入了 第四層 {} 裡面格式是 (小類名稱:{ })
246 #這個layer_30就是最後一層的四位數資料了 格式: ('0111', '稻谷種植') 是一個tuple 索引0是編碼1是名稱
247 small_class=layer_30[1]
248 # print("小類名稱:\n",small_class)
249 #--------------------------------------------------------------------------------
250 # 判斷字元串
251 if (qb03 == layer_30[0]):
252 print("正常四位小類判斷成功!", qb03)
253 flag=True
254 res=items[0]+qb03+"·"+category+"·"+big_class+"·"+medium_class+"·"+small_class
255 return res
256 #這裡是對沒有找到的編碼進行二次尋找,字元串拼接,最前面加個0
257 if(flag==False):
258 new_qb03="0"+qb03
259 return ger_stdstr(new_qb03,stdfilepwd) #遞歸調用自身
260
261 """
262 ------------------------------------------------------------------------------------------------------------------------
263 """
264
265 def do_clean(filepwd,newfilepwd,stdfilepwd):
266 """
267 1、讀取源資料表格
268 2、逐個把資料傳入get_stdstr(qb03,stdfilepwd)方法獲得傳回值存回excel表格
269 參數:需要清洗的行業編碼,單列資料
270 filepwd,需要清洗的檔案
271 newfilepwd,新生成的檔案存儲路徑
272 stdfilepwd,标準的國标檔案
273 :return:None
274 """
275 """
276 待清洗的檔案格式:filepwd
277 QB03
278 2812
279 3511
280 3071
281 3434
282 2614
283 3620
284 2613
285 2614
286 3512
287
288 清洗完畢的檔案格式:newfilepwd
289 data
290 2812·制造業·化學纖維制造業·纖維素纖維原料及纖維制造·人造纖維(纖維素纖維)制造
291 3511·制造業·專用裝置制造業·采礦、冶金、建築專用裝置制造·礦山機械制造
292 3071·制造業·非金屬礦物制品業·陶瓷制品制造·衛生陶瓷制品制造
293 3434·制造業·通用裝置制造業·物料搬運裝置制造·連續搬運裝置制造
294 2614·制造業·化學原料和化學制品制造業·基礎化學原料制造·有機化學原料制造
295 3620·制造業·汽車制造業·改裝汽車制造·改裝汽車制造
296 2613·制造業·化學原料和化學制品制造業·基礎化學原料制造·無機鹽制造
297 2614·制造業·化學原料和化學制品制造業·基礎化學原料制造·有機化學原料制造
298 3512·制造業·專用裝置制造業·采礦、冶金、建築專用裝置制造·石油鑽采專用裝置制造
299 3599·制造業·專用裝置制造業·環保、社會公共服務及其他專用裝置制造·其他專用裝置制造
300 511·批發和零售業·批發業·農、林、牧産品批發·農、林、牧産品批發
301 3821·制造業·電氣機械和器材制造業·輸配電及控制裝置制造·變壓器、整流器和電感器制造
302 6520·資訊傳輸、軟體和資訊技術服務業·軟體和資訊技術服務業·資訊系統內建服務·資訊系統內建服務
303 7330·科學研究和技術服務業·研究和試驗發展·農業科學研究和試驗發展·農業科學研究和試驗發展
304 2922·制造業·橡膠和塑膠制品業·塑膠制品業·塑膠闆、管、型材制造
305 """
306 df=pd.read_excel(filepwd)
307 # print(df.loc[0].values)
308 res=[]
309 temp_res=""
310 #range(len(df.index.values))
311 for i in range(len(df.index.values)):
312 # print(df.loc[i].values[0])
313 """
314 ger_stdstr()
315 兩個參數 一個是待查編碼 一個是标準json檔案路徑
316 """
317 temp_res=ger_stdstr(str(df.loc[i].values[0]),stdfilepwd)
318 print(temp_res)
319 if(temp_res!=None):
320 res.append(temp_res)
321 else:
322 res.append(str(df.loc[i].values[0]))
323 # print(res)
324 #把結果存儲到excel表
325 workbook = xlwt.Workbook(encoding='utf-8')
326 sheet = workbook.add_sheet('sheet1', cell_overwrite_ok=True)
327 sheet.col(0).width=256*100
328 sheet.write(0, 0, "DATA")
329 for i in range(len(res)):
330 sheet.write(i+1, 0, res[i])
331 workbook.save(newfilepwd)
332 return None
333 if __name__ == '__main__':
334 #封裝方法getjson()
335 """
336 1、封裝建構json的方法 getjson() , 方法有一個參數 參數是檔案路徑
337 檔案的格式是兩列,由于讀取檔案不包括表頭,如果表頭資料有需要的話 需要複制一行表頭資料
338 第一列是行業編碼 第二列是行業名稱
339 """
340 #測試調用
341 stdfilepwd="GBT4754-2011.xlsx"
342 # get_json(stdfilepwd)
343 """
344 --------------------------------------------------------------
345 """
346
347 #封裝方法do_clean(filepwd,newfilepwd,stdfilepwd)
348 # 測試調用
349 filepwd="2013_year_data.xlsx" #需要處理的檔案路徑13年
350 newfilepwd="2013_res_data.xls" #處理完畢轉存的檔案路徑13年
351
352 filepwd16 = "2016_year_data.xlsx" # 需要處理的檔案路徑16年
353 newfilepwd16 = "2016_res_data.xls" # 處理完畢轉存的檔案路徑16年
354 do_clean(filepwd16, newfilepwd16, stdfilepwd)
355
356 """
357 --------------------------------------------------------------
358 """
359 #封裝ger_stdstr(qb03,jsonfilepwd) 方法 參數1是四位待查編碼 參數2是json檔案的路徑
360 # res=ger_stdstr("321",stdfilepwd)
361 # print(res)