區分Protobuf 3中缺失值和默認值

2020-12-17 新世界雜貨鋪

來自公眾號:新世界雜貨鋪

這兩天翻了翻以前的項目,發現不同項目中關於Protobuf 3缺失值和默認值的區分居然有好幾種實現。今天筆者冷飯新炒,結合項目中的實現以及切身經驗共總結出如下六種方案。

增加標識欄位

眾所周知,在Go中數字類型的默認值為0(這裡僅以數字類型舉例),這在某些場景下往往會引起一定的歧義。

以is_show欄位為例,如果沒有該欄位表示不更新DB中的數據,如果有該欄位且值為0則表示更新DB中的數據為不可見,如果有該欄位且值為1則表示更新DB中的數據為可見。

上述場景中,實際要解決的問題是如何區分默認值和缺失欄位。增加標識欄位是通過額外增加一個欄位來達到區分的目的。

例如:增加一個has_show_field欄位標識is_show是否為有效值。如果has_show_field為true則is_show為有效值,否則認為is_show未設置值。

此方案雖然直白,但每次設置is_show的值時還需設置has_show_field的值,甚是麻煩故筆者十分不推薦。

欄位含義和默認值區分

欄位含義和默認值區分即不使用對應類型的默認值作為該欄位的有效值。接著前面的例子繼續描述,is_show為1時表示展示,is_show為2時表示不展示,其他情況則認為is_show未設置值。

此方案筆者還是比較認可的,唯一問題就是和開發者的默認習慣略微不符。

使用oneof

oneof 的用意是達到 C 語言 union 數據類型的效果,但是諸多大佬還是發現它可以標識缺失欄位。

上述proto文件生成對應go文件後,Test.St為Status的指針類型,故通過此方案可以區分默認值和缺失欄位。但是筆者認為此方案做json序列化時十分不友好,下面是筆者的例子:

上述輸出結果如下:

通過上述輸出知,oneof的json.Marshal輸出結果會額外多一層,而json.Unmarshal還會失敗,因此使用oneof時需謹慎。

使用wrapper類型

這應該是google官方提出的解決方案,我們看看下面的例子:

使用此方案需要引入google/protobuf/wrappers.proto。此方案生成對應go文件後,Test.St也是Status的指針類型。同樣,我們也看一下它的json序列化效果:

上述輸出結果如下:

和oneof方案相比wrapper方案的json反序列化是沒問題的,但是json.Marshal的輸出結果也會額外多一層。另外,經筆者在本地試驗,此方案無法和gogoproto一起使用。

允許proto3使用optional標籤

前面幾個方案估計在實踐中還是不夠盡善盡美。於是2020年5月16日protoc v3.12.0發布,該編譯器允許proto3的欄位也可使用 optional修飾。

下面看看例子:

此方案需要使用新版本的protoc且必須使用--experimental_allow_proto3_optional開啟此特性。protoc升級教程見https://github.com/protocolbuffers/protobuf#protocol-compiler-installation。下面繼續看看該方案的json序列化效果

上述輸出結果如下:

據上述結果知,此方案與oneof以及wrapper方案的json序列化相比更加符合預期,同樣,經筆者在本地試驗,此方案無法和gogoproto一起使用。

proto2和proto3結合使用

作為一個gogoproto的忠實用戶,筆者希望在能區分默認值和缺失值的同時還可以繼續使用gogoproto的特性。於是便產生了proto2和proto3結合使用的野路子。

需要區分缺失欄位和默認值的message定義在語法為proto2的文件中,proto3通過import導入proto2的message以達區分目的。

optional修飾的欄位在Go中會生成指針類型,因此區分缺失值和默認值就變的十分容易了。下面看看此方案的json序列化效果:

上述輸出結果如下:

根據上述結果知,此方案不僅能夠活用gogoproto的各種tag,其結果也和在proto3中直接使用optional效果一致。雖然筆者已經在自己的項目中使用了此方案,但是仍然要提醒一句:「寫本篇文章時,筆者特意去github看了gogoproto的發布日誌,gogoproto最新一個版本發布時間為2019年10月14日,筆者大膽預言gogoproto以後不會再更新了,所以此方案還請大家酌情使用」。

最後,衷心希望本文能夠對各位讀者有一定的幫助。

註:文中筆者所用go版本為:go1.15.2文中筆者所用protoc版本為:3.14.0文章中所用完整例子:https://github.com/Isites/go-coder/blob/master/pbjson/main.go

相關焦點

  • Kaggle知識點:缺失值處理
    寫在前面在進行數據競賽中,數據預處理階段經常需要對數據進行缺失值處理。關於缺失值的處理並沒有想像中的那麼簡單。以下為一些經驗分享,基本涵蓋了大部分處理方式。另一個變量X』,將缺失值設為c(可以是任何常數),存在值設為本身。隨後,對X』,D和其他變量(因變量和其他預設模型中的自變量)進行回歸。這種調整的好處是它利用了所有可用的缺失數據的信息(是否缺失)。為了便利,一個好的c的設置方式是現有非缺失數據X的均數。
  • 手把手教你用pandas處理缺失值
    pandas對象的所有描述性統計信息默認情況下是排除缺失值的。pandas對象中表現缺失值的方式並不完美,但是它對大部分用戶來說是有用的。對於數值型數據,pandas使用浮點值NaN(Not a Number來表示缺失值)。
  • 運用R進行缺失值填補
    本節將會學習到:缺失值數據的快速查看及其可視化缺失值的填補方法:均值法、KNN法、決策樹法等運用mice包實現多重填補方法數據填補的可視化缺失值概述缺失數據主要有兩種類型:1.MCAR:完全隨機缺失,這是數據缺失的理想狀況。
  • 數據的預處理基礎:如何處理缺失值
    查看數據中的缺失值,您的第一項工作是基於3種缺失值機制來識別缺失模式:MCAR(完全隨機丟失):如果數據的缺失與任何值(觀察或缺失)之間沒有關係,則為MCAR。當統計過程使用包含某些缺失數據的案例時,將發生成對刪除。 該過程不能包含特定變量,但是當分析具有非缺失值的其他變量時,該過程仍然實用。 例如,假設有3個變量:A,B和C。變量A包含缺失值。 但這不會阻止某些統計過程使用相同的情況來分析變量B和C。成對刪除允許您使用更多數據。 它試圖使Listwise刪除中發生的損失最小化。
  • 離群值與缺失值的識別與處理
    ,出現離群值和缺失值的情況非常常見。 單變量離群值的識別與處理直方圖法:繪製數據直方圖,落在圖形兩端並距離均數的個體值可能就是離群值箱式圖法:繪製箱式圖,如果個體值距離箱式圖底線(25% 線)和頂線(75%線)的距離過大,一般為四分位數間距(箱體高度)的1.5倍至3倍時被視為離群點;而個體值距離箱體底線或頂線距離超過3倍的箱體高度被視為離群值。
  • 機器學習之缺失值處理
    上篇對機器學習中的數據分析進行了詳細介紹,想了解的可以看上篇文章哈缺失值數據圖片比較小,其實這段時間的數據缺失值還是較多的(我是特意找了段缺失值多的數據,方便我們後面對比不同處理方法的結果,嘿嘿~~~),這裡面我們以temp_out欄位為例來進行下面的缺失值處理啦
  • XGBoost缺失值引發的問題及其深度分析|CSDN博文精選
    XGBoost4j中缺失值的處理XGBoost4j缺失值的處理過程發生在構造DMatrix過程中,默認將0.0f設置為缺失值:/*** create DMatrix from dense matrix*
  • R語言如何檢測和處理數據缺失值?
    面對一份數據,我們會做數據的缺失值檢測和分析,根據數據的缺失程度,以知道數據的完整性和可用性。實際的數據,絕大部分會有缺失值現象。缺失值的產生與諸多因素有關聯,例如:數據採集不成功,數據採集成功了但是數據確實沒有值,數據的值受其它因素控制等。面對有缺失值的數據,我們要怎麼處理、分析和應用,是我們數據工作者要思考和實踐的命題。
  • 數據分析|R-缺失值處理
    數據中往往會有各種缺失值,異常值,錯誤值等,今天先介紹一下如何處理缺失值,才能更好的數據分析,更準確高效的建模。一 查看數據集的缺失情況    R中使用NA代表缺失值,用is.na識別缺失值,返回值為TRUE或FALSE。由於邏輯值TRUE和FALSE分別等價於數值1和0,可用sum()和mean()來獲取數據集的缺失情況。
  • 機器學習基礎:缺失值的處理技巧
    在數據分析和建模中,經常會遇到變量值缺失的情況,這是非常常見的。為了保證數據指標的完整性以及可利用性,通常我們會採取特殊的方式對其進行處理。 方式2:常量填充 在進行缺失值填充之前,我們要先對缺失的變量進行業務上的了解,即變量的含義、獲取方式、計算邏輯,以便知道該變量為什麼會出現缺失值、缺失值代表什麼含義。比如,『age』 年齡缺失,每個人均有年齡,缺失應該為隨機的缺失,『loanNum』貸款筆數,缺失可能代表無貸款,是有實在意義的缺失。
  • 歐式距離如何應對缺失值?
    (dat)122.236068這有點反直覺,實際上你再搞個缺失值,它算出來還是一樣的:> dat[1,3] = NA> dist(dat) 12 2.236068首先從代碼上看,缺失值會被去掉,這就是count計數看有多少有效值的作用。如果我們簡單粗爆地把NA值去掉,我們會算出來什麼值呢?
  • Python數據清洗(二):缺失值識別與處理
    缺失值指的是由於人為或機器等原因導致數據記錄的丟失或隱瞞,缺失值的存在一定程度上會影響後續數據分析和挖掘的結果,所以對他的處理將顯得尤為重要。缺失值的識別判斷一個數據集是否存在缺失觀測,通常從兩個方面入手,一個是變量的角度,即判斷每個變量中是否包含缺失值;另一個是數據行的角度,即判斷每行數據中是否包含缺失值。
  • 缺失值插補方法程序和數據release, 總結加註解
    , 步驟和方法供參考這篇文章異常值和缺失值處理環節和步驟, 讓數據具有總體代表性告訴咱們什麼時候使用如下即將引薦的缺失值填補方法。數據的缺失僅僅依賴於完全變量。3.非隨機,不可忽略缺失(Not Missing at Random,NMAR, or nonignorable)。不完全變量中數據的缺失依賴於不完全變量本身,這種缺失是不可忽略的。缺失值插補針對兩種大的類型:單一插補(single imputation)和多重插補(multiple imputation)。
  • 獨家 | 在機器學習中利用統計插補來處理缺失值(附代碼)
    這是一個非常受歡迎的方法,因為對於訓練集很容易計算出一列的統計值,另外這種方法所獲得的效果也比較理想。在這篇教程中,你會了解到在機器學習領域如何利用統計插補來處理缺失值。缺失值必須被標記為NaN,且可以被用統計方法計算出的列的值來替代。如何載入一份帶有缺失值的CSV文件,用NaN來標識缺失值,展現出每一列的缺失值數量和百分比。
  • 「統計實戰」缺失值識別與處理
    關注我的,分析數據不發愁了不信你試試後臺留言,獲取統計軟體在科學研究中,缺失值通常難以避免,但處理起來又比較麻煩,很多人選擇忽略缺失值,但有些時候它們會不知不覺給我們造成麻煩,學幾招缺失值識別和處理的技術還是很有必要的。
  • 如何使用python技術完成數據集缺失值多種應用場景的濾除或填充?
    比如,我們會用數據分析統計數據集中的缺失值、異常值,更直觀的也會進階到數據可視化的部分(到達該部分一般是成了文章類或匯報類的一部分),然後以統計結果為基礎再對數據進行處理。這個過程往往不是一次性過程,是循環往復的。然後數據處理的結果是有質量的,對後期的數據挖掘、機器學習、深度學習以及其他更多的應用,提供了堅實的基礎。接下來,我們就一起來梳理和總結一下,數據處理過程中,經常遇到的缺失值處理方法。
  • 3000字詳解四種常用的缺失值處理方法
    實際上標籤變量和特徵之間可以相互轉化,所以利用這種方法就可以填補特徵矩陣中含有缺失值的特徵,尤其適用於一個特徵缺失值很多,其餘特徵數據很完整,特別標籤變量那一列的數據要完整。但是往往一個特徵矩陣中很多特徵都含有缺失值,對於這種情況,可以從特徵缺失值最少的一個開始,因為缺失值越少的特徵需要的信息也就越少。
  • 統計分析零單系列第五期:缺失值處理(專題)
    缺失值取決於其假設值(例如,高收入人群通常不希望在調查中透露他們的收入);或者,缺失值取決於其他變量值(假設女性通常不想透露她們的年齡,則這裡年齡變量缺失值受性別變量的影響)。基於未知信息的推理插補:研究者可以採用先前研究的數據,或利用priorknowledge來插補缺失值,稱為冷層插補法(colddeck)熱層和冷層的最大區別是:冷層插補是一種外在產生程序,而熱層則是依據研究樣本本身取得缺失值的估計值,即內部產生程序,是更為通用的方法。後面介紹的其他插補法也都是內在產生程序。推理插補法具有十分鮮明的特徵:一是推理插補無須對缺失機制、缺失模式和缺失值的分布做多餘假設。
  • 機器學習基礎:缺失值的處理技巧(附Python代碼)
    在數據分析和建模中,經常會遇到變量值缺失的情況,這是非常常見的。為了保證數據指標的完整性以及可利用性,通常我們會採取特殊的方式對其進行處理。
  • 樣本缺失值處理,你真的操作對了嗎?
    缺失值取決於其假設值(例如,高收入人群通常不希望在調查中透露他們的收入);或者,缺失值取決於其他變量值(假設女性通常不想透露她們的年齡,則這裡年齡變量缺失值受性別變量的影響)。在前兩種情況下可以根據其出現情況刪除缺失值的數據,而在第三種情況下,刪除包含缺失值的數據可能會導致模型出現偏差。因此我們需要對刪除數據非常謹慎。請注意,插補數據並不一定能提供更好的結果。