我有下表:
DATA:
Lines <- " ID MeasureX MeasureY x1 x2 x3 x4 x5
1 1 1 1 1 1 1 1
2 1 1 0 1 1 1 1
3 1 1 1 2 3 3 3"
DF <- read.table(text = Lines, header = TRUE, as.is = TRUE)
我想要达到的目标是:
创建5列(r1-r5)
这是每列x1-x5与MeasureX的划分(例如x1 / measurex,x2 / measurex等)
创建5列(p1-p5)
是每列x1-x5的分区,编号为1-5(xcolumns的数量)示例x1 / 1,x2 / 2等。
MeasureY与现在无关,最终产品将是ID和列r1-r5和p1-p5,这是否可行?
在SAS中我会选择这样的东西:
data test6;
set test5;
array x {5} x1- x5;
array r{5} r1 - r5;
array p{5} p1 - p5;
do i=1 to 5;
r{i} = x{i}/MeasureX;
p{i} = x{i}/(i);
end;
原因在于更具动态性,因为未来列数可能会发生变化。
答案 0 :(得分:2)
参数回收允许您使用常量向量进行元素分割。棘手的部分是从列名中提取数字。然后我按行数重复每个数字以执行第二次除法任务。
DF[ ,paste0("r", 1:5)] <- DF[ , grep("x", names(DF) )]/ DF$MeasureX
DF[ ,paste0("p", 1:5)] <- DF[ , grep("x", names(DF) )]/ # element-wise division
rep( as.numeric( sub("\\D","",names(DF)[ # remove non-digits
grep("x", names(DF))] #returns only 'x'-cols
) ), each=nrow(DF) ) # make them as long as needed
#-------------
> DF
ID MeasureX MeasureY x1 x2 x3 x4 x5 r1 r2 r3 r4 r5 p1 p2 p3 p4 p5
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0.5 0.3333333 0.25 0.2
2 2 1 1 0 1 1 1 1 0 1 1 1 1 0 0.5 0.3333333 0.25 0.2
3 3 1 1 1 2 3 3 3 1 2 3 3 3 1 1.0 1.0000000 0.75 0.6
如果你已经知道第二个除法任务的序列向量是1-5,这可以大大简化,但这是为了允许列名的序列中的“间隙”,并仍然使用名称中的数字信息作为除数。 (你并不完全清楚这个代码将在什么情况下使用。)SAS中{r}的构造由[ , paste0('r', 1:5)]
模仿。 SAS是一种宏语言,有时候有经验的用户无法弄清楚如何让R表现得像一个人。通常,需要一段时间才能失去for循环心态并开始使用R作为函数式语言。
答案 1 :(得分:2)
使用data.table
包的替代方案:
cols <- names(df[c(4:8)])
library(data.table)
setDT(df)[, (paste0("r",1:5)) := .SD / df$MeasureX, by = ID, .SDcols = cols
][, (paste0("p",1:5)) := .SD / 1:5, by = ID, .SDcols = cols]
导致:
> df
ID MeasureX MeasureY x1 x2 x3 x4 x5 r1 r2 r3 r4 r5 p1 p2 p3 p4 p5
1: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0.5 0.3333333 0.25 0.2
2: 2 1 1 0 1 1 1 1 0 1 1 1 1 0 0.5 0.3333333 0.25 0.2
3: 3 1 1 1 2 3 3 3 1 2 3 3 3 1 1.0 1.0000000 0.75 0.6
答案 2 :(得分:1)
你可以整理一个漂亮的循环或申请这样做,但在这里明确:
# Handling the "r" columns.
DF$r1 <- DF$x1 / DF$MeasureX
DF$r2 <- DF$x2 / DF$MeasureX
DF$r3 <- DF$x3 / DF$MeasureX
DF$r4 <- DF$x4 / DF$MeasureX
DF$r5 <- DF$x5 / DF$MeasureX
# Handling the "p" columns.
DF$p1 <- DF$x1 / 1
DF$p2 <- DF$x2 / 2
DF$p3 <- DF$x3 / 3
DF$p4 <- DF$x4 / 4
DF$p5 <- DF$x5 / 5
# Taking only the columns we want.
FinalDF <- DF[, c("ID", "r1", "r2", "r3", "r4", "r5", "p1", "p2", "p3", "p4", "p5")]
注意到这是非常简单的矩阵操作,你绝对可以在其他地方找到它。也许你是R的新手,但下次还要付出更多的努力。如果您是R的新手,那么查找一些基本的R编码教程或视频绝对值得花时间。