R:按列应用归一化函数 - 大 DataFrame/DataTable
R: Applying normalization function column wise - large DataFrame/DataTable
我有一个很大的 r data.frame,有将近 500 列。我想添加现有的比例函数,并以列方式尝试不同的规范化函数。
截至现有比例函数
library(dplyr)
set.seed(1234)
dat <- data.frame(x = rnorm(10, 30, .2),
y = runif(10, 3, 5),
z = runif(10, 10, 20), k = runif(10, 5, 10))
dat %>% mutate_each_(funs(scale),vars=c("y","z"))
问题 1:
在这种情况下,vars 只有两个,但是当您有 500 列来规范化时,最好的方法是什么?
我试过以下:
dnot <- c("y", "z")
dat %>% mutate_each_(funs(scale),vars=!(names(dat) %in% dnot))
错误:
Error in UseMethod("as.lazy_dots") :
no applicable method for 'as.lazy_dots' applied to an object of class "logical"
问题 2:我不想使用内置的缩放函数,而是想应用我自己的函数来规范化数据框。
示例:我有以下功能
normalized_columns <- function(x)
{
r <- (x/sum(x))
}
问题 2:我如何才能有效地将其应用于所有列,同时仅保留 3 或 4 列。
有更好的方法,但我通常会这样做:
set.seed(1234)
x = rnorm(10, 30, .2)
y = runif(10, 3, 5)
z = runif(10, 10, 20)
k = runif(10, 5, 10)
a = rnorm(10, 30, .2)
b = runif(10, 3, 5)
c = runif(10, 10, 20)
d = runif(10, 5, 10)
normalized_columns <- function(x)
{
x/sum(x)
}
dat<-data.frame(x,y,z,k,a,b,c,d)
dat[,c(1,4,6:8)]<-sapply(dat[,c(1,4,6:8)], normalized_columns)
编辑:就效率而言,这是相当快的:
set.seed(100)
dat<-data.frame(matrix(rnorm(50000, 5, 2), nrow = 100, ncol = 500))
cols<-sample.int(500, 495, replace = F)
system.time(dat[,cols]<-sapply(dat[,cols], normalized_columns))
##user system elapsed
##0.03 0.00 0.03
由于 OP 使用 dplyr
方法,一种选择是使用 setdiff
和 mutate_each_
dat %>%
mutate_each_(funs(scale), setdiff(names(dat), dnot))
# x y z k
#1 -0.8273937 3.633225 14.56091 0.22934964
#2 0.6633811 3.605387 12.65187 0.76742806
#3 1.4738069 3.318092 13.04672 -1.16688369
#4 -1.9708424 3.079992 15.07307 0.62528427
#5 0.8157183 3.437599 11.81096 -1.06313355
#6 0.8929749 4.621197 17.59671 -0.06743894
#7 -0.1923930 4.051395 12.01248 0.94484655
#8 -0.1641660 4.829316 12.58810 -0.16575678
#9 -0.1820615 4.662690 19.92150 -1.55940662
#10 -0.5090247 3.091541 18.07352 1.45571106
或根据逻辑索引
对 names
进行子集化
dat %>%
mutate_each_(funs(scale), names(dat)[!names(dat) %in% dnot])
# x y z k
#1 -0.8273937 3.633225 14.56091 0.22934964
#2 0.6633811 3.605387 12.65187 0.76742806
#3 1.4738069 3.318092 13.04672 -1.16688369
#4 -1.9708424 3.079992 15.07307 0.62528427
#5 0.8157183 3.437599 11.81096 -1.06313355
#6 0.8929749 4.621197 17.59671 -0.06743894
#7 -0.1923930 4.051395 12.01248 0.94484655
#8 -0.1641660 4.829316 12.58810 -0.16575678
#9 -0.1820615 4.662690 19.92150 -1.55940662
#10 -0.5090247 3.091541 18.07352 1.45571106
如果我们使用mutate_each
,另一个选项是one_of
dat %>%
mutate_each(funs(scale), -one_of(dnot))
# x y z k
#1 -0.8273937 3.633225 14.56091 0.22934964
#2 0.6633811 3.605387 12.65187 0.76742806
#3 1.4738069 3.318092 13.04672 -1.16688369
#4 -1.9708424 3.079992 15.07307 0.62528427
#5 0.8157183 3.437599 11.81096 -1.06313355
#6 0.8929749 4.621197 17.59671 -0.06743894
#7 -0.1923930 4.051395 12.01248 0.94484655
#8 -0.1641660 4.829316 12.58810 -0.16575678
#9 -0.1820615 4.662690 19.92150 -1.55940662
#10 -0.5090247 3.091541 18.07352 1.45571106
带有 data.table
的 setdiff
选项将是
library(data.table)
nm1 <- setdiff(names(dat), dnot)
setDT(dat)[, (nm1) := lapply(.SD, scale), .SDcols = nm1]
我有一个很大的 r data.frame,有将近 500 列。我想添加现有的比例函数,并以列方式尝试不同的规范化函数。
截至现有比例函数
library(dplyr)
set.seed(1234)
dat <- data.frame(x = rnorm(10, 30, .2),
y = runif(10, 3, 5),
z = runif(10, 10, 20), k = runif(10, 5, 10))
dat %>% mutate_each_(funs(scale),vars=c("y","z"))
问题 1: 在这种情况下,vars 只有两个,但是当您有 500 列来规范化时,最好的方法是什么? 我试过以下:
dnot <- c("y", "z")
dat %>% mutate_each_(funs(scale),vars=!(names(dat) %in% dnot))
错误:
Error in UseMethod("as.lazy_dots") :
no applicable method for 'as.lazy_dots' applied to an object of class "logical"
问题 2:我不想使用内置的缩放函数,而是想应用我自己的函数来规范化数据框。
示例:我有以下功能
normalized_columns <- function(x)
{
r <- (x/sum(x))
}
问题 2:我如何才能有效地将其应用于所有列,同时仅保留 3 或 4 列。
有更好的方法,但我通常会这样做:
set.seed(1234)
x = rnorm(10, 30, .2)
y = runif(10, 3, 5)
z = runif(10, 10, 20)
k = runif(10, 5, 10)
a = rnorm(10, 30, .2)
b = runif(10, 3, 5)
c = runif(10, 10, 20)
d = runif(10, 5, 10)
normalized_columns <- function(x)
{
x/sum(x)
}
dat<-data.frame(x,y,z,k,a,b,c,d)
dat[,c(1,4,6:8)]<-sapply(dat[,c(1,4,6:8)], normalized_columns)
编辑:就效率而言,这是相当快的:
set.seed(100)
dat<-data.frame(matrix(rnorm(50000, 5, 2), nrow = 100, ncol = 500))
cols<-sample.int(500, 495, replace = F)
system.time(dat[,cols]<-sapply(dat[,cols], normalized_columns))
##user system elapsed
##0.03 0.00 0.03
由于 OP 使用 dplyr
方法,一种选择是使用 setdiff
和 mutate_each_
dat %>%
mutate_each_(funs(scale), setdiff(names(dat), dnot))
# x y z k
#1 -0.8273937 3.633225 14.56091 0.22934964
#2 0.6633811 3.605387 12.65187 0.76742806
#3 1.4738069 3.318092 13.04672 -1.16688369
#4 -1.9708424 3.079992 15.07307 0.62528427
#5 0.8157183 3.437599 11.81096 -1.06313355
#6 0.8929749 4.621197 17.59671 -0.06743894
#7 -0.1923930 4.051395 12.01248 0.94484655
#8 -0.1641660 4.829316 12.58810 -0.16575678
#9 -0.1820615 4.662690 19.92150 -1.55940662
#10 -0.5090247 3.091541 18.07352 1.45571106
或根据逻辑索引
对names
进行子集化
dat %>%
mutate_each_(funs(scale), names(dat)[!names(dat) %in% dnot])
# x y z k
#1 -0.8273937 3.633225 14.56091 0.22934964
#2 0.6633811 3.605387 12.65187 0.76742806
#3 1.4738069 3.318092 13.04672 -1.16688369
#4 -1.9708424 3.079992 15.07307 0.62528427
#5 0.8157183 3.437599 11.81096 -1.06313355
#6 0.8929749 4.621197 17.59671 -0.06743894
#7 -0.1923930 4.051395 12.01248 0.94484655
#8 -0.1641660 4.829316 12.58810 -0.16575678
#9 -0.1820615 4.662690 19.92150 -1.55940662
#10 -0.5090247 3.091541 18.07352 1.45571106
如果我们使用mutate_each
,另一个选项是one_of
dat %>%
mutate_each(funs(scale), -one_of(dnot))
# x y z k
#1 -0.8273937 3.633225 14.56091 0.22934964
#2 0.6633811 3.605387 12.65187 0.76742806
#3 1.4738069 3.318092 13.04672 -1.16688369
#4 -1.9708424 3.079992 15.07307 0.62528427
#5 0.8157183 3.437599 11.81096 -1.06313355
#6 0.8929749 4.621197 17.59671 -0.06743894
#7 -0.1923930 4.051395 12.01248 0.94484655
#8 -0.1641660 4.829316 12.58810 -0.16575678
#9 -0.1820615 4.662690 19.92150 -1.55940662
#10 -0.5090247 3.091541 18.07352 1.45571106
带有 data.table
的 setdiff
选项将是
library(data.table)
nm1 <- setdiff(names(dat), dnot)
setDT(dat)[, (nm1) := lapply(.SD, scale), .SDcols = nm1]