99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁精彩閱讀R字符串處理應用之郵件考勤自動化
R字符串處理應用之郵件考勤自動化
2017-07-05
收藏

R字符串處理應用之郵件考勤自動化

最近發(fā)現(xiàn),擔任助教真不是一件輕松的事情啊。雖然老師一直在想方設法減輕我的工作負擔,可是核對名單真的是一件考驗眼力和耐力的事情。

最近有一件非常艱巨的任務:檢查上周的『考勤郵件』。這個『考勤郵件』,容我耐心的解釋一番。上周,老師為了不浪費大家的時間,通過在某幾分鐘內(nèi)發(fā)送一封郵件到公共郵箱的方法來簽到。

而我今天才拿到選課學生的名單。我們知道,郵件過了一段時間,標題顯示的接收時間就會改變。這個時候,為了確定郵件的發(fā)送時間,我必須要每封郵件都打開來看一下,再找到相應的名單,然后打上一個滿意的勾。然而,這可是五十多封郵件?。。。?

立志成為數(shù)(一)據(jù)(名)科(懶)學(人)家的我,怎能甘心做如此機械的活呢?于是,想起最近總結的一篇字符處理相關的博客,正好可以用上。

說干就干!下面,我們就來探索一番,如何用R實現(xiàn)郵件考勤全自動化。

載入數(shù)據(jù)

首先,從公共郵箱批量下載數(shù)據(jù)。并載入R。

library(stringr)
library(openxlsx)
#load Name list

NameInformation<-read.xlsx("data/名單_20160308.xlsx",sheet = 1,colNames = TRUE)
str(NameInformation)
NameList<-NameInformation$姓名
NameList<-str_trim(NameList)
#read E-mail name
EmailName<-dir("data/第一次考勤/信件打包")

查看缺勤人員名單

載入數(shù)據(jù)的第一步,當然是先看看是否全勤啦~

如果沒人缺勤,后面的日期提取等臟活累活就可以不用干啦!(再次暴露了懶人的本性= =!)

#match name list,remove E-mails which's subject NOT contain names ON the namelist

# detact weather the subject contains the name
ExistStatus<-lapply(NameList, function(x){
  Exist<-str_detect(EmailName,x)
  return(sum(Exist))
})

ExistStatus<-unlist(ExistStatus)

# find not checked names
print(paste0("缺勤的同學:",NameList[!ExistStatus]))

#str_detect(EmailName,"張三")

果不其然,有些同學還是不夠團結啊!有幾個沒發(fā)郵件的。當然,謹慎的黃老師還是用str_detect()函數(shù)重新核對了一下,誤傷了同學可不好辦吶。

提取郵件接收時間

打開文本編輯器,仔細看了一下幾封郵件,發(fā)現(xiàn)日期格式大概是這樣的:

Date: Wed, 2 Mar 2016 08:06:28 +0800

先將郵件內(nèi)容讀入一個list。接著,用正則表達式,把含有Date: Wed, 2 Mar 2016字樣的這一行提取出來。然后,只提取我們需要的時間。最后,使用striptime()函數(shù)將字符串轉(zhuǎn)換成時間格式。然而,在Windows下一直得到的返回值一直是NA,在Linux下可以正確轉(zhuǎn)換。萬惡的微軟!

###########################
## check in email received time   ###
# get email content
 
EmailContent<-lapply(EmailName,function(x){
  readLines(con<-file(paste0("data/第一次考勤/信件打包/",x),encoding = 'UTF-8'))
})

# get date and time
EmailDate<-lapply(EmailContent,function(x){
  date_vec<-str_subset(x,"Date: Wed, 2 Mar 2016")
  date<-str_sub(date_vec,start = 7, end = 30)
  return(date)
})


# format conveting
## windows 下有問題,linux下沒問題
EmailDate<-lapply(EmailDate,function(x){
  strptime(x,"%a, %d %b %Y %I:%M:%S")
})

EmailDate<-unlist(EmailDate)

提取名字

為了做到有憑有據(jù),還是要從主題提取一下名字。這個時候,跟已有的選課名單進行一一匹配即可。

然而,我們的課實在太火爆!有些沒有選到課的同學,為了刷刷自己的存在感,也發(fā)來了『賀電』。這可不好辦!?。∪绻且粋€個核對,找了半天,發(fā)現(xiàn)沒在選課名單上,豈不氣煞人也!然而,有了R,我只需要一個IF語句就搞定啦。

還有一些不知是手抖還是為了刷存在感,的同學,連發(fā)了幾封E-mail。當然,我并沒有生氣,我只需要一行代碼就可以輕松化解難題。

########################################33
## exteact name on the subject     ##

NameOnSubject<-lapply(EmailName,function(x){
  ExtractName<-str_extract(x,NameList)
  ## 有的同學沒有選課也發(fā)了郵件,或者不小心下載了垃圾郵件
  if(sum(is.na(ExtractName))==51){
    return(NA)
  }
  else{
    Name<- ExtractName[!is.na(ExtractName)]
    return(Name)
  }
})

### combine Date and name
NameOnSubject<-unlist(NameOnSubject)

EmailData<-data.frame(CheckTime= EmailDate,NameOnSubject = NameOnSubject,stringsAsFactors = FALSE)

#先去掉名字為NA的郵件
EmailData<-EmailData[!is.na(EmailData$NameOnSubject),]

# 有的同學手抖,發(fā)了幾封郵件,需要去重
EmailData<-EmailData[!duplicated(EmailData[,"NameOnSubject"]),]

View(EmailData)
str(EmailData)

合并數(shù)據(jù)

最后,跟選課名單進行合并即大功告成啦!

CheckInNameList<-data.frame(Name = NameInformation$姓名,CheckInStatus = ExistStatus)
str(CheckInNameList)
# merge namelist and the EmailData
CheckInNameData<-merge(x = CheckInNameList, y = EmailData, by.x = "Name",
      by.y = "NameOnSubject",all = TRUE,all.x = TRUE )

library(DT)
datatable(CheckInNameData)

其實仔細想想,郵箱考勤這個機制存在很大的bug。

我們可以一起發(fā)揮智慧,思考一下如何加入防作弊機制。如給每個在場的人發(fā)送一個唯一的隨機碼隨郵件發(fā)送?(不想上課的同學會不會打我?!逃~~~~)


數(shù)據(jù)分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個參數(shù)驗證碼對象,之后可以使用它調(diào)用相應的接口 initGeetest({ // 以下 4 個配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺檢測極驗服務器是否宕機 new_captcha: data.new_captcha, // 用于宕機時表示是新驗證碼的宕機 product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說明請參見:http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計時完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }