首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用R中的同一函数修改数据集的多列

使用R中的同一函数修改数据集的多列
EN

Stack Overflow用户
提问于 2016-06-05 17:58:45
回答 3查看 2.7K关注 0票数 3

下面是生成data.frame的代码:

代码语言:javascript
复制
ref_variables=LETTERS[1:10]
row=100
d0=seq(1:100)
for (i in seq_along(ref_variables)){
  dtemp=sample(seq(1:row),row,TRUE)
  d0=data.frame(d0,dtemp)
}
d0[,1]=NULL
names(d0)=ref_variables

我有一个数据集,data.frame或data.table,随便什么。假设我想修改第2列到第4列,方法是将它们中的每一列除以第一列。当然,我可以像这样做一个循环:

代码语言:javascript
复制
columns_name_to_divide=c("B","C","H")
column_divisor="A"
for (i in seq_along(columns_name_to_divide)){        
  ds[columns_name_to_divide[i]] = ds[columns_name_to_divide[i]] / ds[column_divisor]
}

但是,有没有一种更优雅的方法呢?

EN

回答 3

Stack Overflow用户

发布于 2016-06-05 18:06:34

代码语言:javascript
复制
  > d0[2:4] <- d0[,2:4]/d0[,1]  

这将用你在第2,3,4列除以第1列后得到的结果替换你的原始值。其余的将保持不变。

如果您希望在将第2、3、4列除以第1列后,在d0中使用新值创建3个新列,则不会替换第2、3和4列中的原始值。计算值将分别位于第11、12和13列中。

代码语言:javascript
复制
  > dim(d0)
  # [1] 100  10
  > d0[11:13] <- d0[,2:4]/d0[,1]
  > dim(d0)
  # [1] 100  13

要对新值进行四舍五入,只需将round()函数添加到两个小数位,如下所示:

代码语言:javascript
复制
  > d0[2:4] <- round(d0[,2:4]/d0[,1],2)  # Original values subtituted at 2,3,4

  # OR

  > d0[11:13] <- round(d0[,2:4]/d0[,1],2)  # New columns added, original columns are untouched.
票数 4
EN

Stack Overflow用户

发布于 2016-06-05 18:12:17

我们可以从data.table中使用set,这将使效率更高,因为在多次调用时避免了.[data.table的开销(尽管不是在这种情况下)。

代码语言:javascript
复制
library(data.table)
setDT(d0)
for(j in columns_name_to_divide){
   set(d0, i = NULL, j = j, value = d0[[j]]/d0[[column_divisor]])
}

或者使用lapply

代码语言:javascript
复制
setDT(d0)[, (columns_name_to_divide) := lapply(.SD, `/`, 
              d0[[column_divisor]]), .SDcols = columns_name_to_divide]

或者是使用dplyr的优雅选择

代码语言:javascript
复制
library(dplyr)
library(magrittr)
d0 %<>%
    mutate_each_(funs(./d0[[column_divisor]]), columns_name_to_divide)
head(d0)
#  A         B         C  D  E  F  G        H  I  J
#1 60 0.4000000 1.1500000  6 86 27 19 0.150000 94 97
#2 11 0.6363636 0.3636364 25 52 44 82 8.818182 84 68
#3 80 0.8750000 1.1375000 72 34 56 69 0.125000 34 17
#4 77 0.3116883 1.0259740  9 44 87 61 1.064935 79 40
#5 18 0.3333333 5.0555556 60 69 62 89 2.166667 21 34
#6 42 1.3333333 2.3095238 61 20 87 95 1.428571 78 63

基准测试

代码语言:javascript
复制
set.seed(42)
d1 <- as.data.frame(matrix(sample(1:9, 1e7*7, replace=TRUE), ncol=7))

d2 <- copy(d1)
d3 <- copy(d1)

system.time({
d2 %<>%
   mutate_each(funs(./d2[["V2"]]), V4:V7)
})
# user  system elapsed 
#   0.52    0.39    0.91 

system.time({
d1[,4:7] <- d1[,4:7]/d1[,2]
})
#   user  system elapsed 
#   1.72    0.72    2.44 


system.time({

setDT(d3)
for(j in 4:7){
   set(d3, i = NULL, j = j, value = d3[[j]]/d3[["V2"]])
}

})
#  user  system elapsed 
#   0.32    0.16    0.47 
票数 2
EN

Stack Overflow用户

发布于 2016-06-05 18:19:17

您可以这样做:

代码语言:javascript
复制
library(data.table)


cols <- names(df)[2:4]
col1 <- names(df)[1]

setDT(df)[, (cols) := lapply (cols, function(x)  get(x) / get(col1) )]


# sample data for reproducible example:
df <- data.frame(V1=rep(10,5),
                 V2=rep(20,5),
                 V3=rep(30,5),
                 V4=rep(40,5),
                 V5=rep(50,5))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37640608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档