R-如何通过从列名中提取项的名称来添加新列来创建新表?

R-如何通过从列名中提取项的名称来添加新列来创建新表?,r,dataframe,R,Dataframe,我有一个带有列名的data.frame: Machine1.workingTime, Machine2.workingTime, Machine3.workingTime, Machine1.producedItems, Machine2.producedItems, ... 随着时间的推移,这个框架可以随着更多的机器而扩展。 我需要制作一个R脚本,在这里我必须获得此解决方案: workingTime, producedItems, MachineNum 其中MachineNum是从中获取数

我有一个带有列名的
data.frame

Machine1.workingTime, Machine2.workingTime, Machine3.workingTime,
Machine1.producedItems, Machine2.producedItems, ...
随着时间的推移,这个框架可以随着更多的机器而扩展。 我需要制作一个R脚本,在这里我必须获得此解决方案:

workingTime, producedItems, MachineNum
其中MachineNum是从中获取数据的列中的数字。(例如,如果我获取Machine2.workingTime列并将其添加到新创建的列“workingTime”,则“MachineNum”将为2

我必须遍历整个
data.frame
,并将列合并到新列中,新列的部分名称为旧的原始名称(例如workingTime) 并从旧原始列名的第一部分筛选MachineNum

在过去的几个小时里,我一直在尝试和搜索,但我找不到任何解决方案。

我想(希望)这是关于你正在寻找的。我知道我的答案不是最简洁的,我期待着看到其他更清晰的答案

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
library(data.table)#对于melt()和merge(),其他包具有类似的函数。
#虚拟数据帧

df这里是一种使用
reformate2
库的方法

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)
更新(2017年12月2日):响应注释,如果没有其他标识符来唯一区分一台机器的多行,可以使用聚合函数对每台机器进行一次观察

theResult <- dcast(meltedData,machineId ~ columnName,
                   fun.aggregate=mean,value.var="value")
head(theResult)
更新(2017年12月2日):响应评论,使用唯一序列号区分数据行的解决方案如下所示

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)

请提供包含您的数据框(或与您的数据框类似的合成数据)的代码示例显示了你走了多远以及在哪里遇到了麻烦。不清楚这些是列名还是列中的值。什么是
MachineNum
我认为你要搜索的关键字是长格式与宽格式数据,以及如何从长格式转换到宽格式。如果你提供示例数据,你可能会得到更好的答案。我有cre我用所需的列创建了一个新的数据框架。所以workingTime、producesItems、MachineNum等等。我现在需要用大表中的数据填充这个框架,在这个大表中我必须通过检查列名进行筛选。因此,我通过筛选列名并将字符串与新列名进行比较来找出保存位置,但我不知道如何进行。Machine2.workingTime必须过滤为“workingTime”2将此列的值插入新的workingTime列,将2插入machineNum列。必须对整个选项卡执行此操作,在该选项卡中,我最多可以获得1000台机器DF_wt$machineNum,如果您没有日期,我想您需要一些id变量来标记跟踪观察结果……我可以以某种方式使用初始行数吗his似乎一直工作到result@Rnooby-除非数据帧中只有一行,否则您需要某种方法来区分输出中的多行与
dcast()
。@snoram的解决方案强调了相同的问题:您需要某种ID变量来区分每个机器ID的多行,或者需要使用聚合函数,如
sum()
mean()
。我可以使用初始行数吗?我对R很陌生,这一点我自己很难理解。谢谢大家的帮助。@Rnooby请使用
dput()好吗
在您的问题中发布一些数据,以便我们查看输入?然后我们可以帮助您获得正确的结果。此外,如果您觉得答案有用,请向上投票/接受答案。我无法发布数据,但我可以描述融化的数据的外观。列名:变量、值、columnName、machineNumber.variable和columnName几乎是一样的。变量像Machine_01.workingTime等等。coulumnNames就是workingTime等等。这看起来很不错。我必须把它们放在一个表中,看起来像这样:MachineNumber,workingTime,振动率,producedItems,(所有其他列名都是列)但是没有唯一的字段。每一行中都可以有dublicated。因此,第1行的值可以与第2行、第3行的值相同,依此类推。
> head(theResult)
  machineId producedItems workingTime
1         1         105.5         5.5
2         2         205.5        25.5
> 
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
>