k-匿名(k-Anonymity)
生活随笔
收集整理的這篇文章主要介紹了
k-匿名(k-Anonymity)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文鏈接:【k-匿名(k-Anonymity)代碼實現】差分隱私代碼實現系列(三)_k匿名實現_粥粥粥少女的擰發條鳥的博客-CSDN博客
import pandas as pd import numpy as np import matplotlib.pyplot as plt #plt.style.use('seaborn-whitegrid') raw_data = {'first_name': ['Jason', 'Molly', 'Tina', 'Jake', 'Amy'],'last_name': ['Miller', 'Jacobson', 'Ali', 'Milner', 'Cooze'],'age': [42, 52, 36, 24, 73],'preTestScore': [4, 24, 31, 2, 3],'postTestScore': [25, 94, 57, 62, 70]} #df = pd.DataFrame(raw_data, columns = ['first_name', 'last_name', 'age', 'preTestScore', 'postTestScore']) df = pd.DataFrame(raw_data, columns = ['age', 'preTestScore', 'postTestScore']) print(df)# 循環訪問行,對于每一行,我們查詢數據記錄以查看有多少行與準標識符的值匹配。 # 如果任何組中的行數小于k,則數據幀不滿足該值k-Anonymity,我們返回 False。 # 請注意,在這個簡單的定義中,我們認為所有列都包含準標識符;要將檢查限制為所有列的子集,我們需要將表達式替換為其他內容。 # 當k=1的時候是滿足條件的返回true def isKAnonymized(df, k):for index, row in df.iterrows():query = ' & '.join([f'{col} == {row[col]}' for col in df.columns])rows = df.query(query)if rows.shape[0] < k: #len(rows)return Falsereturn True print(isKAnonymized(df, 1)) #isKAnonymized(df, 2)#這個函數里面的y表示表中實際數據,比如42。depths[x.name]表示當前屬性下設定的映射值,下面在depths中將各個屬性設為1,也就是對42/10再*10得到40。整個函數就是對所有數字向下取到10的倍數。 def generalize(df, depths):return df.apply(lambda x: x.apply(lambda y: int(int(y/(10**depths[x.name]))*(10**depths[x.name]))))#嘗試將每列概括為一個"級別" , 即舍入到最接近的10。 depths = {'age': 1,'preTestScore': 1,'postTestScore': 1 } df2 = generalize(df, depths) print(df2) print(isKAnonymized(df2, 2))#可以嘗試泛化更多,但隨后我們最終會刪除所有數據!各個屬性的深度又1變成2,等于是42/100直接為0了。 depths = {'age': 2,'preTestScore': 2,'postTestScore': 2 } df2 = generalize(df, depths) print(df2) print(isKAnonymized(df2, 2))'''age preTestScore postTestScore 0 42 4 25 1 52 24 94 2 36 31 57 3 24 2 62 4 73 3 70 trueage preTestScore postTestScore 0 40 0 20 1 50 20 90 2 30 30 50 3 20 0 60 4 70 0 70 Falseage preTestScore postTestScore 0 0 0 0 1 0 0 0 2 0 0 0 3 0 0 0 4 0 0 0 true ''' import pandas as pd import numpy as np import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid')# 循環訪問行,對于每一行,我們查詢數據記錄以查看有多少行與準標識符的值匹配。 # 如果任何組中的行數小于k,則數據幀不滿足該值k-Anonymity,我們返回 False。 # 請注意,在這個簡單的定義中,我們認為所有列都包含準標識符;要將檢查限制為所有列的子集,我們需要將表達式替換為其他內容。 # 當k=1的時候是滿足條件的返回true def isKAnonymized(df, k):for index, row in df.iterrows():query = ' & '.join([f'{col} == {row[col]}' for col in df.columns])rows = df.query(query)if rows.shape[0] < k: #len(rows)return Falsereturn True #這個函數里面的y表示表中實際數據,比如42。depths[x.name]表示當前屬性下設定的映射值,下面在depths中將各個屬性設為1,也就是對42/10再*10得到40。整個函數就是對所有數字向下取到10的倍數。 def generalize(df, depths):return df.apply(lambda x: x.apply(lambda y: int(int(y/(10**depths[x.name]))*(10**depths[x.name]))))#新的數據集 adult_data = pd.read_csv("PUMS.csv") print(adult_data.head())#當前情況k = 2的 k-Anonymity不滿足,k = 1的k-Anonymity已經滿足。 df = adult_data[['age', 'educ']] df.columns = ['ages', 'educs'] print(isKAnonymized(df.head(100), 1)) #isKAnonymized(df.head(100), 2)#老方法,調用generalize對數據進行處理。結果仍然不滿足 depths = {'ages': 1,'educs': 1 } df2 = generalize(df.head(1000), depths) print(isKAnonymized(df2, 2))#刪除異常值(Removing Outliers),使用Numpy的方法來執行此裁剪。我們將年齡裁剪為50歲或以下,而將教育水平單獨保留(通過將其裁剪為非常大的值)。 #DataFrame.clip(lower=None, upper=None, axis=None, inplace=False, *args, **kwargs) depths = {'ages': 1,'educs': 1 } dfp = df.clip(upper=np.array([50, 10000000000000]), axis='columns') df2 = generalize(dfp.head(500), depths) print(isKAnonymized(df2, 4)) #滿足k = 4 的k-Anonymity '''age sex educ race income married pid 0 59 1 9 1 0.0 1 1 1 31 0 1 3 17000.0 0 2 2 36 1 11 1 0.0 1 3 3 54 1 11 1 9100.0 1 4 4 39 0 5 3 37000.0 0 5 True False True '''本文鏈接👍:對數據集進行k匿名(k-Anonymity)處理(python)——以adult數據集為例_tales_teller的博客-CSDN博客
'''導包,導入字符串配置''' import numpy as np import pandas as pd # 配置信息 # 數據集文件路徑 censusData_FilePath ='D://Codes/data set/adult/adult.data' # 屬性標簽 attributeLabels = ["age", # 0年齡 int64"workclass", # 1工作類型 object"fnlwgt", # 2人口特征權重 int64"education", # 3學歷 object"education_num", # 4受教育時間 int64"marital_status", # 5婚姻狀態 object"occupation", # 6職業 object"relationship", # 7關系 object"race", # 8種族 object"sex", # 9性別 object"capital_gain", # 10資本收益 int64"capital_loss", # 11資本損失 int64"hours_per_week", # 12每周工作小時數 int64"native_country", # 13原籍 object"wage_class"] # 14收入類別 object # 準標識符 quasi_identifier_list = [] quasi_identifier_DGH_list = [] quasi_identifier_VGH_list = [] quasi_identifier_height_list = []'''引入準標識符信息''' # marital-status屬性標簽 marital_attributeLabels = ['***', # 0抑制標簽'Married-h2', # 1已婚'Alone', # 2獨自一人'Married-h1', # 3已婚'Single', # 4單身'Widowhood', # 5鰥寡'Married-civ-spouse', # 已婚-公民-配偶'Married-AF-spouse', # 已婚-無房-配偶'Separated', # 分居'Divorced', # 離婚'Never-married', # 未婚'Widowed', # 寡居'Married-spouse-absent' # 已婚-配偶-不在] # marital-status的泛化樹 vgh_marital = pd.DataFrame({'value': marital_attributeLabels,'parent': [-1, 0, 0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5],'height': [3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]}) quasi_identifier_list.append(attributeLabels[5]) # 將marital-status設置為準標識符 quasi_identifier_DGH_list.append(3) quasi_identifier_VGH_list.append(vgh_marital) quasi_identifier_height_list.append(0) print(vgh_marital)# race屬性標簽 race_attributeLabels = ['***', # 0抑制標簽'White-h1', # 1白人'Non-White', # 2非白人'White', # 3白人'Asian-Pac-Islander', # 亞洲-太平洋-伊斯蘭人'Amer-Indian-Eskimo', # 美洲-印第安人-愛斯基摩人'Other', # 其他'Black' # 黑人] # race的泛化樹 vgh_race = pd.DataFrame({'value': race_attributeLabels,'parent': [-1, 0, 0, 1, 2, 2, 2, 2],'height': [2, 1, 1, 0, 0, 0, 0, 0]}) quasi_identifier_list.append(attributeLabels[8]) # 將workclass設置為準標識符 quasi_identifier_DGH_list.append(2) quasi_identifier_VGH_list.append(vgh_race) quasi_identifier_height_list.append(0) print(vgh_race)#如果還要增加其他準標識符,以類似的格式加上就可以了。但是數值型屬性需要先分段,不能直接使用。 # # marital-status屬性標簽 # marital_attributeLabels = ['***', # 0抑制標簽 # 'Married-h2', # 1已婚 # 'Alone', # 2獨自一人 # 'Married-h1', # 3已婚 # 'Single', # 4單身 # 'Widowhood', # 5鰥寡 # 'Married-civ-spouse', # 已婚-公民-配偶 # 'Married-AF-spouse', # 已婚-無房-配偶 # 'Separated', # 分居 # 'Divorced', # 離婚 # 'Never-married', # 未婚 # 'Widowed', # 寡居 # 'Married-spouse-absent' # 已婚-配偶-不在 # ] # # marital-status的泛化樹 # vgh_marital = pd.DataFrame({'value': marital_attributeLabels, # 'parent': [-1, 0, 0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5], # 'height': [3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]}) # quasi_identifier_list.append(attributeLabels[5]) # 將marital-status設置為準標識符 # quasi_identifier_DGH_list.append(3) # quasi_identifier_VGH_list.append(vgh_marital) # quasi_identifier_height_list.append(0) # print(vgh_marital)'''導入數據集初步準備''' # 導入數據集 censusData_Set = pd.read_csv(censusData_FilePath, names=attributeLabels)# 將缺失值部分的“ ?” 置為空,即 np.NaN,便于使用pandas來處理缺失值 censusData_Set = censusData_Set.replace(" ?", np.NaN)# 類型為字符串的標簽 attributeLabels_str = ["workclass", "education", "marital_status", "occupation","relationship", "race", "sex", "native_country", "wage_class"] # 刪除數據值前的空格 for label in attributeLabels_str:censusData_Set[label] = censusData_Set[label].str.strip()# 刪除包含缺失值的行 censusData_Set.dropna(inplace=True) # 重置索引 censusData_Set.reset_index(drop=True, inplace=True) print(censusData_Set[['marital_status','race']].head(n=15))'''檢查數據集是否滿足K匿名''' # 檢驗是否滿足k匿名 # 將所有準標識符的組合存入字典,值為出現次數。 def group_data(testedSet):quasiDict = {}for item in testedSet.itertuples():# --------------------------------------------------------------# 將準標識符轉化為字符串item_statement = ''for label in quasi_identifier_list:item_statement = item_statement + getattr(item, label) + ' '# --------------------------------------------------------------# 如果該準標識符組合已經出現過了,則計數+1if item_statement in quasiDict.keys():quasiDict[item_statement] += 1# 如果該準標識符組合沒有出現過,則新建記錄else:quasiDict[item_statement] = 1# 返回字典return quasiDict# 判斷數據集testedSet是否滿足k匿名,是則返回true,否則返回false def if_k(testedSet, k):# 對數據集進行分組,獲得組合數量ans_dict = group_data(testedSet)# -----------------------------------------------------------------# 展示準標識符組合print('')print(ans_dict)print('')# -----------------------------------------------------------------min_k = None# 遍歷分組字典,取出最小的重復個數,賦值給min_kfor i in ans_dict:if min_k is None or ans_dict[i] < min_k:min_k = ans_dict[i];# 如果字典的最小k值大于等于給定的k值,則滿足k匿名if min_k >= k:return Trueelse:return False'''泛化''' #對數據集tempDataSet(dataframe)的屬性列attr(String)進行泛化 #vgh(dataframe)是泛化樹 def Generalization_attr(tempDataSet, attr, vgh, h):for index,row in vgh.iterrows():if row.height==h:tempDataSet.replace({attr:row.value},vgh.loc[row.parent].value,inplace=True)'''運行主函數''' # 演示取值:16000;2;15;140 k_Anonymity = 15 # 泛化次數計數,初始化為所有準標識符泛化次數之和 gen_count = 0 for index in range(len(quasi_identifier_DGH_list)):gen_count += quasi_identifier_DGH_list[index]while if_k(censusData_Set, k_Anonymity) is False:for index in range(len(quasi_identifier_list)):# 如果已經到達了泛化頂點if quasi_identifier_height_list[index] >= quasi_identifier_DGH_list[index]:continue# -----------------------------------------------------------------# 泛化Generalization_attr(censusData_Set,quasi_identifier_list[index],quasi_identifier_VGH_list[index],quasi_identifier_height_list[index])# -----------------------------------------------------------------# 泛化次數-1gen_count -= 1# 泛化高度+1quasi_identifier_height_list[index] += 1if if_k(censusData_Set, k_Anonymity):breakprint('當前泛化高度:')for index in range(len(quasi_identifier_list)):print(quasi_identifier_list[index] + ':' + str(quasi_identifier_height_list[index]))# 直至無法泛化if gen_count == 0:print('泛化失敗')breakprint('當前泛化高度:') for index in range(len(quasi_identifier_list)):print(quasi_identifier_list[index] + ':' + str(quasi_identifier_height_list[index]))print(f'當前k值為:{k_Anonymity}')prec = 0 for index in range(len(quasi_identifier_list)):prec += (quasi_identifier_height_list[index]) / (quasi_identifier_DGH_list[index]) prec = 1 - (prec / len(quasi_identifier_list)) print(f'精確度為:{prec}') print(censusData_Set[['marital_status','race']].head(n=15)) ''' 當前泛化高度: marital_status:1 race:0 當前k值為:15 精確度為:0.8333333333333334marital_status race 0 Single White 1 Married-h1 White 2 Single White 3 Married-h1 Black 4 Married-h1 Black 5 Married-h1 White 6 Widowhood Black 7 Married-h1 White 8 Single White 9 Married-h1 White 10 Married-h1 Black 11 Married-h1 Asian-Pac-Islander 12 Single White 13 Single Black 14 Married-h1 Amer-Indian-Eskimo '''總結
以上是生活随笔為你收集整理的k-匿名(k-Anonymity)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Html中使用jquery通过Ajax请
- 下一篇: 网站提示“error 522”怎么解决?