2017年10月5日 星期四

台灣人力市場價

ptt-tech_job-M.1507055381.A.6A7

昨天看到大神按讚,剛好掃了這篇:[心得] 我的薪資歷程史 (續4) - 看板 Tech_Job - 批踢踢實業坊,感到健康又溫馨,所以來記錄一下。

我自己的心得...其實美國、中國和台灣的價目的確有很明顯的起薪差距,當你了解這個生態時,通常已深陷在某一個區域難以自拔,像是人已在矽谷、人在上海,或是人在台灣抱怨著數字 XD 台灣這邊大多都是看著鄉民的分享,且 PTT 有太多負面的情緒,且真正高薪者都忙得喘不過氣,要嘛工作,要嘛忙著訂機票排假期,誰跟你在那邊浪費時間處理負面心情,時間就是金錢啊!

在同業交流上,得到的資訊跟這位強者分享的極吻合。像是矽谷起薪好則 8~12萬鎂,六年資歷的資深等級拿到 30萬鎂的也有。而台灣的外商價也如上述對應,如大大的年資拿到一百八的數字,要超過也是有的,通常得搭配天時地利人和,拿了個二百五也不是不行。而這些是建立在生態圈,已穩健成長的公司,會願意花錢找強者,而完成A輪的新創,更是會花多錢來加速的公司成長的,因此,拿到高於行情時,要承擔的是面對收掉的風險,而拿到低於市場行情時,要想想自己的吃虧是為了什麼,想透了才會走得遠,最怕就是人云亦云,永遠不知幾兩重 Orz

回過頭來,我覺得台灣的人力價為了避免惡性競爭,大多都會說好一個範圍,太高就會碰到 HR 的思維:那其他成員該怎辦。而這樣是不是好事?也說不上來。只知道若一間公司起薪範圍屬於可接受的價碼,那剩下就好好珍惜,雖然跳槽是數字變化最快的方式(例如10%~50%)且不用等上一整年後才調薪,但公司若還有機會時,可跟這位大大一樣深耕,求一個不會虧待你的公司、有願景的公司,並且等待他起飛。

舉些對應例子:某強者當初離開 hTC 加入新創(當時股價還沒破千),他的新創老闆偶爾都會碎碎唸幾句“不好意思讓你少賺了”,但強者還是甘之如飴(在新創也過得很讚) ;前同事當初待在 hTC 趁勢賺了間中和房;負面的,則是分紅費用化,當時拿到 hTC 的股票繳的稅 > 死抱著股票的餘值。

總之,一切看緣分,強求不來啊,但時時努力是必要的,不要帶著負面心情、懷才不遇、惡習文化來圈地搞政治,重要的,求的是公司強盛後的分紅,而不是那份起薪啊

2017年9月30日 星期六

[Python] 機器學習筆記 - Feature Engineering 以鐵達尼號資料為例

之前都用一些工作經驗去分析一些資料,但不夠科學,有點僥倖的做事方式。如果碰到沒任何背景經驗的數據時,這時就慘了,就得回歸到靠數學統計了。

參考這篇:Titanic best working Classifier by Sina

整個過程十分享受如何用平均、標準差、去除雜訊、資料補齊、正規化、標籤數據化等等。讓我回想起之前寫的筆記,用了 LabelEncoder 等方式,結果...只要用 Pandas 搭配 map 架構就一口氣做光了 XD 並非 LabelEncoder 無用武之地,而是當你清楚資料屬性時,可以善用 Pandas 的架構去達成。而此例未用 OneHotEncoder 架構。

簡易筆記:

train = pd.read_csv('../input/train.csv', header = 0, dtype={'Age': np.float64})
test  = pd.read_csv('../input/test.csv' , header = 0, dtype={'Age': np.float64})
full_data = [train, test]

for dataset in full_data:
        dataset['Name_length'] = dataset['Name'].apply(len)
dataset['Has_Cabin'] = dataset["Cabin"].apply(lambda x: 0 if type(x) == float else 1)


用個 full_data = [train, test] 再搭配 "for dataset in full_data " 的好處是可以一口氣整理完 train/test dataset 的轉換,十方便利,之前完全沒想到這招。新增欄位就透過 pandas 架構直接添加,非常直觀,但沒想到可以一口氣搭配 apply 架構去處理,這樣程式超簡潔的:

dataset['Name_length'] = dataset['Name'].apply(len)
dataset['Has_Cabin'] = dataset["Cabin"].apply(lambda x: 0 if type(x) == float else 1)


另外,在字串處理時,可以搭配 replace 或 regular expression(apply) 做前置處理(正規化):

def get_title(name):
title_search = re.search(' ([A-Za-z]+)\.', name)
if title_search:
return title_search.group(1)
return ""

dataset['Title'] = dataset['Name'].apply(get_title)
#print(dataset['Title'].unique())
dataset['Title'] = dataset['Title'].replace(['Lady', 'Countess','Capt', 'Col','Don', 'Dr', 'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Rare')
dataset['Title'] = dataset['Title'].replace('Mlle', 'Miss')
dataset['Title'] = dataset['Title'].replace('Ms', 'Miss')
dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs')
#print(dataset['Title'].unique())


整理完一輪後,把字串轉數據,就可以透過 map 來轉換,其中 fillna 則是把剩下沒對應到的都填 0 ,簡潔啊:

title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
dataset['Title'] = dataset['Title'].map(title_mapping)
dataset['Title'] = dataset['Title'].fillna(0)


接著來處理年紀與票價的部分,由於偏隱私,容易無資料,這時看到作者就開始用亂數去填補年紀,並依照著標準差資訊來做,可以維持資料分布,高招!而票價則用中位數去填補:

age_avg = dataset['Age'].mean()
age_std = dataset['Age'].std()
age_null_count = dataset['Age'].isnull().sum()
age_null_random_list = np.random.randint(age_avg - age_std, age_avg + age_std, size=age_null_count)
#
# dataset['Age'][np.isnan(dataset['Age'])] = age_null_random_list
#
# SettingWithCopyWarning:
# A value is trying to be set on a copy of a slice from a DataFrame
# See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
#
dataset.loc[ dataset['Age'][np.isnan(dataset['Age'])].index , 'Age' ] = age_null_random_list

dataset.loc[ dataset['Age'] <= 16, 'Age'] = 0
dataset.loc[(dataset['Age'] > 16) & (dataset['Age'] <= 32), 'Age'] = 1
dataset.loc[(dataset['Age'] > 32) & (dataset['Age'] <= 48), 'Age'] = 2
dataset.loc[(dataset['Age'] > 48) & (dataset['Age'] <= 64), 'Age'] = 3
dataset.loc[ dataset['Age'] > 64, 'Age'] = 4 ;

dataset['Fare'] = dataset['Fare'].fillna(train['Fare'].median())
dataset.loc[ dataset['Fare'] <= 7.91, 'Fare'] = 0
dataset.loc[(dataset['Fare'] > 7.91) & (dataset['Fare'] <= 14.454), 'Fare'] = 1
dataset.loc[(dataset['Fare'] > 14.454) & (dataset['Fare'] <= 31), 'Fare']   = 2
dataset.loc[ dataset['Fare'] > 31, 'Fare'] = 3
dataset['Fare'] = dataset['Fare'].astype(int)


最後,再提一下新增屬性的部分,pandas 真的很方便,可以單純把某欄位的資訊計算一番,添加到新的欄位,也有透過 dataset.loc 來取得特定資料來重新設定:

dataset['Name_length'] = dataset['Name'].apply(len)
dataset['Has_Cabin'] = dataset["Cabin"].apply(lambda x: 0 if type(x) == float else 1)

dataset['IsAlone'] = 0
dataset.loc[dataset['FamilySize'] == 1, 'IsAlone'] = 1

dataset.loc[ dataset['Age'][np.isnan(dataset['Age'])].index , 'Age' ] = age_null_random_list

dataset.loc[ dataset['Age'] <= 16, 'Age'] = 0
dataset.loc[(dataset['Age'] > 16) & (dataset['Age'] <= 32), 'Age'] = 1


讀完這篇真是功力大增啊!以上是數據整理的流程,但是,還有個重點沒提到,那就是作者是整理完後,立馬看看某欄位跟目標欄位(Survived)的關係,才是真的靠數學來做事:

print (train[["Sex", "Survived"]].groupby(['Sex'], as_index=False).mean())
      Sex  Survived
0  female  0.742038
1    male  0.188908

print (train[['Title', 'Survived']].groupby(['Title'], as_index=False).mean())

    Title  Survived
0  Master  0.575000
1    Miss  0.702703
2      Mr  0.156673
3     Mrs  0.793651
4    Rare  0.347826


可以得知 Miss 跟 Mrs 的生存率超過七成!這才是該學的精神。對於常搭船的,大多很清楚一開始必然先讓婦幼先逃生,所以有背景就會先假定讓女性生存率高的分析方式,沒背景就得靠統計功力了

2017年9月27日 星期三

[Unix] 透過 jq 處理時間比較 @ macOS / jq-1.5

看到同事在處理 AWS AMI 的管理,用到了 jq 在過濾舊版資料來進行刪除,我也練了一下 jq 就順便筆記一下:

$ echo '{}' | jq 'now'
1506504885.298058
$ echo '{}' | jq 'now | gmtime '
[
  2017,
  8,
  27,
  9,
  34,
  47.25080108642578,
  3,
  269
]
$ echo '{}' | jq 'now | gmtime | todate'
"2017-09-27T09:35:00Z"
$ echo '{}' | jq 'now | gmtime | todate[:10]'
"2017-09-27"
$ echo '{}' | jq 'now | todate[:10]'
"2017-09-27"


得到三天前的時間:

$ echo '{}' | jq '(now - 86400*3) | gmtime | todate[:10]'
"2017-09-24"


假想一票資料:

$ echo '[{"StartTime": "2017-09-21T10:32:33.000Z"},{"StartTime": "2017-09-22T10:32:33.000Z"},{"StartTime": "2017-09-26T10:32:33.000Z"},{"StartTime": "2017-09-24T10:32:33.000Z"},{"StartTime": "2017-09-25T10:32:33.000Z"},{"StartTime": "2017-09-19T10:32:33.000Z"},{"StartTime": "2017-09-01T10:32:33.000Z"},{"StartTime": "2017-09-92T10:32:33.000Z"}]' | jq ''
[
  {
    "StartTime": "2017-09-21T10:32:33.000Z"
  },
  {
    "StartTime": "2017-09-22T10:32:33.000Z"
  },
  {
    "StartTime": "2017-09-26T10:32:33.000Z"
  },
  {
    "StartTime": "2017-09-24T10:32:33.000Z"
  },
  {
    "StartTime": "2017-09-25T10:32:33.000Z"
  },
  {
    "StartTime": "2017-09-19T10:32:33.000Z"
  },
  {
    "StartTime": "2017-09-01T10:32:33.000Z"
  },
  {
    "StartTime": "2017-09-92T10:32:33.000Z"
  }
]


挑出超過七天者(此乃字串比對):

$ echo '[{"StartTime": "2017-09-21T10:32:33.000Z"},{"StartTime": "2017-09-22T10:32:33.000Z"},{"StartTime": "2017-09-26T10:32:33.000Z"},{"StartTime": "2017-09-24T10:32:33.000Z"},{"StartTime": "2017-09-25T10:32:33.000Z"},{"StartTime": "2017-09-19T10:32:33.000Z"},{"StartTime": "2017-09-01T10:32:33.000Z"},{"StartTime": "2017-09-92T10:32:33.000Z"}]' | jq '.[] | if (.StartTime[0:10] < (now - (86400* 7) | todate[0:10]) ) then .StartTime else empty end '
"2017-09-19T10:32:33.000Z"
"2017-09-01T10:32:33.000Z"

2017年9月24日 星期日

[戲劇] 大王不容易



又有一陣子沒看戲,更別說是大陸戲劇了。被室友推坑看了一下,前面還滿新鮮的,但後面的滋味有點難述 XD 論其喜好,我比較喜歡前半段的安排,酷酷的女主角很正,男主角娘的很流暢。除此之外,也有發現一位台灣女演員 袁子芸 。我覺得古裝有種像做實驗時,控制變因似的,當大家穿一樣的服裝時,天生麗質的就會被凸顯出來。

說說別的吧,一開始吸引人的是男主角詮釋女主角個性的演技,查了一下 WIKI 才知道男主角 张逸杰 1999 年 9月 2 號出生,前幾天才剛滿18歲而已!女主角 白鹿 是 1994 年 9 月 23 號出生的。原來演戲的跟看戲的都是處女座 XD

看著百度百科,讓人有點感到恐怖,年輕時期就很努力地打拼了,時間啊。

2017年9月19日 星期二

[Python] 機器學習筆記 - 使用 Pandas 處理 CSV 格式、過濾資料與自身 Index 更新問題

使用 Pandas 套件進行分析資料時,它提供的功能包括便利的資料過濾:

import seaborn as sns
import pandas as pd

dataset = sns.load_dataset("tips")
print(dataset)
print(dataset.shape)
print(dataset.columns)

print("list total_bill > 30:")
print(dataset[ dataset['total_bill'] > 30 ] )


然而,預設 Pandas 會記錄原先的 raw index ,這也有不錯的功用,但有時希望照新的架構顯示,需要再多用 reset_index():

print("list total_bill > 30 and tip < 4:")
print(dataset[ (dataset['total_bill'] > 30) & (dataset['tip'] < 4) ] )

print("rebuild index:")
dataset = dataset[ (dataset['total_bill'] > 30) & (dataset['tip'] < 4) ]
dataset = dataset.reset_index()
print(dataset)


連續動作:

$ python pandas_study.py
     total_bill   tip     sex smoker   day    time  size
0         16.99  1.01  Female     No   Sun  Dinner     2
1         10.34  1.66    Male     No   Sun  Dinner     3
2         21.01  3.50    Male     No   Sun  Dinner     3
3         23.68  3.31    Male     No   Sun  Dinner     2
4         24.59  3.61  Female     No   Sun  Dinner     4
5         25.29  4.71    Male     No   Sun  Dinner     4
6          8.77  2.00    Male     No   Sun  Dinner     2
7         26.88  3.12    Male     No   Sun  Dinner     4
8         15.04  1.96    Male     No   Sun  Dinner     2
9         14.78  3.23    Male     No   Sun  Dinner     2
10        10.27  1.71    Male     No   Sun  Dinner     2
11        35.26  5.00  Female     No   Sun  Dinner     4
12        15.42  1.57    Male     No   Sun  Dinner     2
13        18.43  3.00    Male     No   Sun  Dinner     4
14        14.83  3.02  Female     No   Sun  Dinner     2
15        21.58  3.92    Male     No   Sun  Dinner     2
16        10.33  1.67  Female     No   Sun  Dinner     3
17        16.29  3.71    Male     No   Sun  Dinner     3
18        16.97  3.50  Female     No   Sun  Dinner     3
19        20.65  3.35    Male     No   Sat  Dinner     3
20        17.92  4.08    Male     No   Sat  Dinner     2
21        20.29  2.75  Female     No   Sat  Dinner     2
22        15.77  2.23  Female     No   Sat  Dinner     2
23        39.42  7.58    Male     No   Sat  Dinner     4
24        19.82  3.18    Male     No   Sat  Dinner     2
25        17.81  2.34    Male     No   Sat  Dinner     4
26        13.37  2.00    Male     No   Sat  Dinner     2
27        12.69  2.00    Male     No   Sat  Dinner     2
28        21.70  4.30    Male     No   Sat  Dinner     2
29        19.65  3.00  Female     No   Sat  Dinner     2
..          ...   ...     ...    ...   ...     ...   ...
214       28.17  6.50  Female    Yes   Sat  Dinner     3
215       12.90  1.10  Female    Yes   Sat  Dinner     2
216       28.15  3.00    Male    Yes   Sat  Dinner     5
217       11.59  1.50    Male    Yes   Sat  Dinner     2
218        7.74  1.44    Male    Yes   Sat  Dinner     2
219       30.14  3.09  Female    Yes   Sat  Dinner     4
220       12.16  2.20    Male    Yes   Fri   Lunch     2
221       13.42  3.48  Female    Yes   Fri   Lunch     2
222        8.58  1.92    Male    Yes   Fri   Lunch     1
223       15.98  3.00  Female     No   Fri   Lunch     3
224       13.42  1.58    Male    Yes   Fri   Lunch     2
225       16.27  2.50  Female    Yes   Fri   Lunch     2
226       10.09  2.00  Female    Yes   Fri   Lunch     2
227       20.45  3.00    Male     No   Sat  Dinner     4
228       13.28  2.72    Male     No   Sat  Dinner     2
229       22.12  2.88  Female    Yes   Sat  Dinner     2
230       24.01  2.00    Male    Yes   Sat  Dinner     4
231       15.69  3.00    Male    Yes   Sat  Dinner     3
232       11.61  3.39    Male     No   Sat  Dinner     2
233       10.77  1.47    Male     No   Sat  Dinner     2
234       15.53  3.00    Male    Yes   Sat  Dinner     2
235       10.07  1.25    Male     No   Sat  Dinner     2
236       12.60  1.00    Male    Yes   Sat  Dinner     2
237       32.83  1.17    Male    Yes   Sat  Dinner     2
238       35.83  4.67  Female     No   Sat  Dinner     3
239       29.03  5.92    Male     No   Sat  Dinner     3
240       27.18  2.00  Female    Yes   Sat  Dinner     2
241       22.67  2.00    Male    Yes   Sat  Dinner     2
242       17.82  1.75    Male     No   Sat  Dinner     2
243       18.78  3.00  Female     No  Thur  Dinner     2

[244 rows x 7 columns]
(244, 7)
Index(['total_bill', 'tip', 'sex', 'smoker', 'day', 'time', 'size'], dtype='object')
list total_bill > 30:
     total_bill    tip     sex smoker   day    time  size
11        35.26   5.00  Female     No   Sun  Dinner     4
23        39.42   7.58    Male     No   Sat  Dinner     4
39        31.27   5.00    Male     No   Sat  Dinner     3
44        30.40   5.60    Male     No   Sun  Dinner     4
47        32.40   6.00    Male     No   Sun  Dinner     4
52        34.81   5.20  Female     No   Sun  Dinner     4
56        38.01   3.00    Male    Yes   Sat  Dinner     4
59        48.27   6.73    Male     No   Sat  Dinner     4
83        32.68   5.00    Male    Yes  Thur   Lunch     2
85        34.83   5.17  Female     No  Thur   Lunch     4
95        40.17   4.73    Male    Yes   Fri  Dinner     4
102       44.30   2.50  Female    Yes   Sat  Dinner     3
112       38.07   4.00    Male     No   Sun  Dinner     3
141       34.30   6.70    Male     No  Thur   Lunch     6
142       41.19   5.00    Male     No  Thur   Lunch     5
156       48.17   5.00    Male     No   Sun  Dinner     6
167       31.71   4.50    Male     No   Sun  Dinner     4
170       50.81  10.00    Male    Yes   Sat  Dinner     3
173       31.85   3.18    Male    Yes   Sun  Dinner     2
175       32.90   3.11    Male    Yes   Sun  Dinner     2
179       34.63   3.55    Male    Yes   Sun  Dinner     2
180       34.65   3.68    Male    Yes   Sun  Dinner     4
182       45.35   3.50    Male    Yes   Sun  Dinner     3
184       40.55   3.00    Male    Yes   Sun  Dinner     2
187       30.46   2.00    Male    Yes   Sun  Dinner     5
197       43.11   5.00  Female    Yes  Thur   Lunch     4
207       38.73   3.00    Male    Yes   Sat  Dinner     4
210       30.06   2.00    Male    Yes   Sat  Dinner     3
212       48.33   9.00    Male     No   Sat  Dinner     4
219       30.14   3.09  Female    Yes   Sat  Dinner     4
237       32.83   1.17    Male    Yes   Sat  Dinner     2
238       35.83   4.67  Female     No   Sat  Dinner     3
list total_bill > 30 and tip < 4:
print index:
index: 56
index: 102
index: 173
index: 175
index: 179
index: 180
index: 182
index: 184
index: 187
index: 207
index: 210
index: 219
index: 237
rebuild index:
    index  total_bill   tip     sex smoker  day    time  size
0      56       38.01  3.00    Male    Yes  Sat  Dinner     4
1     102       44.30  2.50  Female    Yes  Sat  Dinner     3
2     173       31.85  3.18    Male    Yes  Sun  Dinner     2
3     175       32.90  3.11    Male    Yes  Sun  Dinner     2
4     179       34.63  3.55    Male    Yes  Sun  Dinner     2
5     180       34.65  3.68    Male    Yes  Sun  Dinner     4
6     182       45.35  3.50    Male    Yes  Sun  Dinner     3
7     184       40.55  3.00    Male    Yes  Sun  Dinner     2
8     187       30.46  2.00    Male    Yes  Sun  Dinner     5
9     207       38.73  3.00    Male    Yes  Sat  Dinner     4
10    210       30.06  2.00    Male    Yes  Sat  Dinner     3
11    219       30.14  3.09  Female    Yes  Sat  Dinner     4
12    237       32.83  1.17    Male    Yes  Sat  Dinner     2
print index:
index: 0
index: 1
index: 2
index: 3
index: 4
index: 5
index: 6
index: 7
index: 8
index: 9
index: 10
index: 11
index: 12