我有这个数据框和向量,我想用以下行分割行:
div <- c(10,100,1000)
df <- as.data.frame(matrix(rep(1,9),nrow=3))
df <- cbind(type = as.factor(c("A","B","C")),df)
> df
type V1 V2 V3
1 A 1 1 1
2 B 1 1 1
3 C 1 1 1
我希望以数据框形式提供答案,并保留原因。 将它与矢量分开时,我得到了“错误的”答案:
df1 <- cbind(df[,1], df[,-1]/div)
> df1
df[, 1] V1 V2 V3
1 A 0.100 0.100 0.100
2 B 0.010 0.010 0.010
3 C 0.001 0.001 0.001
我希望每行除以向量,而不是每列。
我的解决方法是:
divfun <- function(x){
x / div
}
df2 <- cbind(df[,1], t(apply(df[,-1], 1, divfun)))
> df2
V1 V2 V3
[1,] 1 0.1 0.01 0.001
[2,] 2 0.1 0.01 0.001
[3,] 3 0.1 0.01 0.001
请注意,这些因素现已丢失。
这里有两个问题:
t()
)?答案 0 :(得分:6)
您正在寻找的功能是sweep()
:
sweep(df[, -1], MARGIN = 2, div, FUN = "/")
> sweep(df[, -1], MARGIN = 2, div, FUN = "/")
V1 V2 V3
1 0.1 0.01 0.001
2 0.1 0.01 0.001
3 0.1 0.01 0.001
因此
cbind(type = df[,1], sweep(df[, -1], 2, div, FUN = "/"))
> cbind(type = df[,1], sweep(df[, -1], 2, div, FUN = "/"))
type V1 V2 V3
1 A 0.1 0.01 0.001
2 B 0.1 0.01 0.001
3 C 0.1 0.01 0.001
获得所需的输出。
请注意,此处,参数MARGIN
并未像1
中那样引用行(2
)或列(apply()
)。在sweep()
中,它指的是与STATS
对应的数组的边距,您希望扫描的向量(在这种情况下除以)。换句话说,STATS
的第一个元素(在您的情况下为div
)是从第1列扫出的值,STATS
的第二个元素是从列中扫出的值2,等等。
答案 1 :(得分:4)
您可以使用转置功能:
> df[,2:4] <- t(t(df[,2:4]) / div)
> df
type V1 V2 V3
1 A 0.1 0.01 0.001
2 B 0.1 0.01 0.001
3 C 0.1 0.01 0.001
答案 2 :(得分:4)
df[,-1] <- df[,-1]/div[col(df)]
df
# type V1 V2 V3
#1 A 0.1 0.01 0.001
#2 B 0.1 0.01 0.001
#3 C 0.1 0.01 0.001
str(df)
#'data.frame': 3 obs. of 4 variables:
# $ type: Factor w/ 3 levels "A","B","C": 1 2 3
# $ V1 : num 0.1 0.1 0.1
# $ V2 : num 0.01 0.01 0.01
# $ V3 : num 0.001 0.001 0.001
set.seed(454)
dat <- as.data.frame(matrix(sample(200, 1e3*1e2, replace=TRUE), ncol=1e2))
set.seed(29)
div <- sample(40, 1e2, replace=TRUE)
f1 <- function() {sweep(dat, MARGIN = 2, div, FUN = "/")}
f2 <- function() {t(t(dat) / div)}
f3 <- function() { mapply("/", dat, div)}
f4 <- function() {dat/div[col(dat)]}
f5 <- function() {for(r in 1:nrow(dat)){
dat[r,]/div}}
library(microbenchmark)
microbenchmark(f1(), f2(), f3(), f4(), f5(), unit="relative")
#Unit: relative
# expr min lq median uq max neval
# f1() 6.765024 6.724991 6.434463 5.124457 10.91735 100
# f2() 1.000000 1.000000 1.000000 1.000000 1.00000 100
# f3() 18.028441 18.551529 16.742279 14.239107 13.72168 100
# f4() 6.315330 6.577099 6.333656 5.052068 10.13038 100
# f5() 4211.839669 3908.555985 3945.130154 2962.534518 1655.12268 100
答案 3 :(得分:2)
或尝试mapply
cbind(df[, 1], mapply("/", df[, -1], div))
## V1 V2 V3
## [1,] 1 0.1 0.01 0.001
## [2,] 2 0.1 0.01 0.001
## [3,] 3 0.1 0.01 0.001
答案 4 :(得分:2)
我喜欢David的解决方案,但我会修改它以将其转换为数据框,因为这样可以保留因子而不是获得矩阵。
data.frame(type=df[, 1], mapply("/", df[, -1], div))
# type V1 V2 V3
#1 A 0.1 0.01 0.001
#2 B 0.1 0.01 0.001
#3 C 0.1 0.01 0.001
这就是我想要的。
答案 5 :(得分:1)
另一种方法:
for(r in 1:nrow(df))
df[r,2:4]= df[r,2:4]/div
df
type V1 V2 V3
1 A 0.1 0.01 0.001
2 B 0.1 0.01 0.001
3 C 0.1 0.01 0.001