Re: [問題] dataframe字串切割

作者: wmj10054039 (MJ)   2018-06-06 17:42:18
※ 引述《celestialgod (天)》之銘言:
: ※ 引述《wmj10054039 (MJ)》之銘言:
: : [問題類型]:
: : 程式諮詢(我想用R 做某件事情,但是我不知道要怎麼用R 寫出來)
: : [軟體熟悉度]:
: : 入門(寫過其他程式,只是對語法不熟悉)
: : [問題敘述]:
: : 我目前整理了一份學校所有課程的時間表,想知道不同星期,不同地點,各時段的
: : 人數統計。dataframe資料範例如下:
: : 流水號 課程名稱 時間 地點 人數
: : 102 A 二3,4四5,7 甲 10
: : 248 B 一1,2,3 乙 20
: : 314 C 三4五7,8,a 丙 5
: : 想請問各位可以用甚麼方法對時間那一欄作字串切割變成以下新的dataframe
: : 流水號 課程名稱 星期 節次 地點 人數
: : 102 A 二 3 甲 10
: : 102 A 二 4 甲 10
: : 102 A 四 5 甲 10
: : 102 A 四 7 甲 10
: : 248 B 一 1 乙 20
: : 248 B 一 2 乙 20
: : . .
: : . .
: : . .
: : 目前想法只有想到for迴圈搭配strspilt,但還是想不到實際寫法,麻煩各位指教了,謝謝
: : [環境敘述]
: : R version 3.4.2
: 程式:
: library(data.table)
: library(pipeR)
: library(stringr)
: dataStr <- "流水號 課程名稱 時間 地點 人數
: 102 A 二3,4四5,7 甲 10
: 248 B 一1,2,3 乙 20
: 314 C 三4五7,8,a 丙 5"
: removeEmptyFunc <- function(x) x[nchar(x) > 0]
: fread(dataStr) %>>%
: `[`(j = `:=`(星期 = str_split(時間, "[a-zA-Z0-9,]+") %>>%
: lapply(removeEmptyFunc),
: 節次 = str_split(時間, "[^a-zA-Z0-9,]+") %>>%
: lapply(removeEmptyFunc))) %>>%
: `[`(j = .(星期 = unlist(星期), 節次 = unlist(節次)),
: by = .(流水號, 課程名稱, 地點, 人數)) %>>%
: `[`(j = `:=`(節次 = str_split(節次, ","))) %>>%
: `[`(j = .(節次 = unlist(節次)), by = .(流水號, 課程名稱, 地點, 人數, 星期))
: ## no pipe 程式碼
: dataDT <- fread(dataStr)
: dataDT[ , `:=`(星期 = lapply(str_split(時間, "[a-zA-Z0-9,]+"),
: removeEmptyFunc),
: 節次 = lapply(str_split(時間, "[^a-zA-Z0-9,]+"),
: removeEmptyFunc))]
: tmpDT <- dataDT[ , .(星期 = unlist(星期), 節次 = unlist(節次)),
: by = .(流水號, 課程名稱, 地點, 人數)]
: tmpDT[ , `:=`(節次 = str_split(節次, ","))]
: tmpDT[ , .(節次 = unlist(節次)), by = .(流水號, 課程名稱, 地點, 人數, 星期)]
: 結果:
: # 流水號 課程名稱 地點 人數 星期 節次
: # 1: 102 A 甲 10 二 3
: # 2: 102 A 甲 10 二 4
: # 3: 102 A 甲 10 四 5
: # 4: 102 A 甲 10 四 7
: # 5: 248 B 乙 20 一 1
: # 6: 248 B 乙 20 一 2
: # 7: 248 B 乙 20 一 3
: # 8: 314 C 丙 5 三 4
: # 9: 314 C 丙 5 五 7
: # 10: 314 C 丙 5 五 8
: # 11: 314 C 丙 5 五 a
我在回應區的問題是想要把如果節次包含3節以上的課程,只取出頭跟尾的節次,並且只有
一節課的課程重複兩次,也就是說每個課程重複在dataframe的次數都會是偶數倍(主要
目的是想知道每個時段下不同地點會產生的進出人數),舉例來說:
流水號 課程名稱 時間 人數 地點
102 A 二3,4四5,7 10 甲
248 B 一1,2,3 20 乙
314 C 三4五7,8,a 5 丙
整理成
流水號 課程名稱 地點 人數 星期 節次
102 A 甲 10 二 3
102 A 甲 10 二 4
. .
. .
. .
248 B 乙 20 一 1
248 B 乙 20 一 3
314 C 丙 5 三 4
314 C 丙 5 三 4
314 C 丙 5 五 7
314 C 丙 5 五 a
我目前的想法是利用c大處理我之前問題的方法,將已經把時間拆開成星期跟節次但
還沒unlist的節次取出,用迴圈搭配條件判斷存成新的list再放回data.frame,但發現
這個方法存成的list只會有最後一個元素有值,其他都是NULL。想請教是哪邊有錯誤,
或是有更好的解決方法,謝謝。
[程式範例]
oldlist = df$節次
newlist = list()
for (i in length(oldlist)) {
if (length(oldlist[[i]]) == 1){
newlist[[i]] = rep(oldlist[[i]][1], 2)
}else if (length(oldlist[[i]]) == 2){
newlist[[i]] = c(oldlist[[i]][1], oldlist[[i]][2])
}else if (length(oldlist[[i]]) == 3){
newlist[[i]] = c(oldlist[[i]][1], olslist[[i]][3])
}
}
作者: wmj10054039 (MJ)   2018-06-07 20:44:00
我知道哪邊寫錯了 感謝~

Links booklink

Contact Us: admin [ a t ] ucptt.com