2017-12-02 152 views
-1

我有一個data.frame列名:R - 如何通過從列名稱中提取項目名稱來添加新列來創建新表格?

Machine1.workingTime, Machine2.workingTime, Machine3.workingTime, 
Machine1.producedItems, Machine2.producedItems, ... 

這個框架可以通過傳遞時間與更多的機器展開。 我需要A R腳本,我一定要得到這個解決方案:

workingTime, producedItems, MachineNum 

凡MachineNum是列從那裏我得到的數據(例如數量,如果我得到Machine2.workingTime列,並加入到。新創建的列「workingTime」「MachineNum」將是2

我必須遍歷整個data.frame並將列合併到具有舊部分名稱的舊名稱(例如workingTime) 和從舊原始列名的第一部分過濾MachineNum。

我嘗試並搜索了最近幾個小時,但找不到任何解決方案。

+0

請提供一個代碼示例,包括您的數據幀(或捏造數據類似於您的數據幀),並顯示你有多遠了,並在那裏你卡住了。 –

+0

不清楚這些列是列名還是列中的值。什麼是'MachineNum' – akrun

+0

我認爲您搜索的關鍵字是長格式與寬格式數據以及如何從其他格式轉換。如果您提供示例數據,您可能會得到更好的答案。 – snoram

回答

0

我想(希望)這是關於你在找什麼。我知道我的答案不是最簡潔的,並期待看到其他更清晰的答案。

library(data.table) # for melt() and merge(), other package have similar func. 

# Dummy data.frame 
df <- data.frame(date = Sys.Date() - 800:1, 
       matrix(sample(0:10000, 2400), ncol = 6)) 
colnames(df)[-1] <- paste0("m", 1:3, c(rep(".wt", 3), rep(".pi", 3))) 
head(df) 
     date m1.wt m2.wt m3.wt m1.pi m2.pi m3.pi 
1 2015-09-24 6271 2491 6525 6680 7708 2949 
2 2015-09-25 1173 5794 5616 7402 3274 8997 
3 2015-09-26 516 6659 2144 8739 7168 1704 
4 2015-09-27 583 2499 4768 9501 2710 6800 
5 2015-09-28 2433 8622 6492 7124 4127 233 
6 2015-09-29 3409 662 6952 3824 5755 9479 

# Now first take working time (filter using regex) to long form 
df_wt <- melt(df[, c("date", grep("wt$", colnames(df), value = TRUE))], 
       id.vars = c("date"), 
       value.name = "workingTime", 
       variable.name = "MachineNum") 
df_wt$MachineNum <- gsub("m([0-9]).+", "\\1", df_wt$MachineNum) 
head(df_wt) 
     date MachineNum workingTime 
1 2015-09-24   1  6271 
2 2015-09-25   1  1173 
3 2015-09-26   1   516 
4 2015-09-27   1   583 
5 2015-09-28   1  2433 
6 2015-09-29   1  3409 

# Same for produced item 
df_pi <- melt(df[, c("date", grep("pi$", colnames(df), value = TRUE))], 
       id.vars = c("date"), 
       value.name = "producedItems", 
       variable.name = "MachineNum") 
df_pi$MachineNum <- gsub("m([0-9]).+", "\\1", df_pi$MachineNum) 
head(df_pi) 
     date MachineNum producedItems 
1 2015-09-24   1   6680 
2 2015-09-25   1   7402 
3 2015-09-26   1   8739 
4 2015-09-27   1   9501 
5 2015-09-28   1   7124 
6 2015-09-29   1   3824 

# Now merge everything 
df_long <- merge(df_wt, df_pi) 
head(df_long) 
     date MachineNum workingTime producedItems 
1 2015-09-24   1  6271   6680 
2 2015-09-24   2  2491   7708 
3 2015-09-24   3  6525   2949 
4 2015-09-25   1  1173   7402 
5 2015-09-25   2  5794   3274 
6 2015-09-25   3  5616   8997 
+0

df_wt $ MachineNum < - gsub(「m([0-9])。+」,「\\ 1」,df_wt $ MachineNum)this似乎沒有工作。我在'$ < - 。data.frame'(* tmp *',testCaseNumber,value = character(0))中得到錯誤: 替換有0行,數據有8347837.列名是Machine_01.workingTime,我不需要使用任何日期。所以我嘗試了沒有id.vars = c(「date」),並得到1只工作時間的一臺機器只有 – Rnooby

+0

如果你沒有日期,我認爲你需要一些id變量來標記觀察記錄... – snoram

+0

我可以用某種方式使用最初的流水號嗎? – Rnooby

0

以下是使用reshape2庫的方法。

machine1.workingTime <- 1:10 
machine2.workingTime <- 21:30 
machine1.producedItems <- 101:110 
machine2.producedItems <- 201:210 
date <- c("2017-01-01","2017-01-02","2017-01-03","2017-01-04","2017-01-05","2017-01-06", 
      "2017-01-07","2017-01-08","2017-01-09","2017-01-10") 


    theData <- data.frame(date, 
         machine1.producedItems, 
         machine1.workingTime, 
         machine2.producedItems, 
         machine2.workingTime 
        ) 

library(reshape2) 

meltedData <- melt(theData,measure.vars=2:5) 
meltedData$variable <- as.character(meltedData$variable) 

# now, extract machine numbers and variable names 
variableNames <- strsplit(as.character(meltedData$variable),"[.]") 
# token after the . is variable name 
meltedData$columnName <- unlist(lapply(variableNames,function(x) x[2])) 
# since all variables start with word 'machine' we can set chars 8+ as ID 
meltedData$machineId <- as.numeric(unlist(lapply(variableNames,function(x) y <- substr(x[1],8,nchar(x[1]))))) 

theResult <- dcast(meltedData,machineId + date ~ columnName,value.var="value") 
head(theResult) 

的結果是:

> head(theResult) 
    machineId  date producedItems workingTime 
1   1 2017-01-01   101   1 
2   1 2017-01-02   102   2 
3   1 2017-01-03   103   3 
4   1 2017-01-04   104   4 
5   1 2017-01-05   105   5 
6   1 2017-01-06   106   6 
> 

UPDATE(02Dec2017):迴應的意見,如果沒有其它標識符來唯一區分的多個行對一臺機器,一個可以使用的聚合功能導致每臺機器觀察一次。

theResult <- dcast(meltedData,machineId ~ columnName, 
        fun.aggregate=mean,value.var="value") 
head(theResult) 

的結果如下。

> head(theResult) 
    machineId producedItems workingTime 
1   1   105.5   5.5 
2   2   205.5  25.5 
> 

UPDATE(02Dec2017):迴應的意見,即使用一個唯一的順序號來區分數據的行的溶液看起來是這樣。

machine1.workingTime <- 1:10 
machine2.workingTime <- 21:30 
machine1.producedItems <- 101:110 
machine2.producedItems <- 201:210 
id <- 1:length(machine1.workingTime) 

theData <- data.frame(id, 
         machine1.producedItems, 
         machine1.workingTime, 
         machine2.producedItems, 
         machine2.workingTime 
) 

meltedData <- melt(theData,measure.vars=2:5) 
head(meltedData) 
meltedData$variable <- as.character(meltedData$variable) 

# now, extract machine numbers and variable names 
variableNames <- strsplit(as.character(meltedData$variable),"[.]") 
meltedData$columnName <- unlist(lapply(variableNames,function(x) x[2])) 
meltedData$machineId <- as.numeric(unlist(lapply(variableNames,function(x) y <- substr(x[1],8,nchar(x[1]))))) 

theResult <- dcast(meltedData,machineId + id ~ columnName,value.var="value") 
head(theResult) 

...和輸出。

head(theResult) 
    machineId id producedItems workingTime 
1   1 1   101   1 
2   1 2   102   2 
3   1 3   103   3 
4   1 4   104   4 
5   1 5   105   5 
6   1 6   106   6 
> 
+0

所以,這似乎工作,直到resultRes <-dcast ...我刪除「+日期」,因爲我不需要任何日期。但是沒有日期,這是行不通的。熔化的數據似乎是正確的。只需要將它從長格式化數據打包到短格式化數據!沒有一個獨特的價值取代日期似乎沒有工作!? – Rnooby

+0

@Rnooby - 除非數據框中只有一行,否則需要用某種方法來區分'dcast()'輸出中的多行。來自@snoram的解決方案強調了同樣的問題:您需要某種ID變量來區分每個機器ID的多行,或者您需要使用像sum()或mean()這樣的聚合函數。 。 –

+0

我可以使用初始排列號嗎?我對R非常陌生,自己很難弄明白。感謝大家的幫助。 – Rnooby

相關問題