R语言 舍入选定的数据列,表

ljo96ir5  于 2023-02-27  发布在  其他
关注(0)|答案(9)|浏览(150)

我有以下数据和代码来圆这个数据表的选定列:

mydf = structure(list(vnum1 = c(0.590165705411504, -1.39939534199836, 
0.720226053660755, -0.253198380120377, -0.783366825121657), vnum2 = c(0.706508400384337, 
0.526770398486406, 0.863136084517464, 0.838245498016477, 0.556775856064633
), vch1 = structure(c(2L, 4L, 1L, 3L, 3L), .Label = c("A", "B", 
"C", "E"), class = "factor")), .Names = c("vnum1", "vnum2", "vch1"
), row.names = c(NA, -5L), class = c("data.table", "data.frame"
))
mydf[,round(.SD,1),]

数学 Dataframe (列表(vnum1 = c(0.590165705411504,-1.39939534199836,:数据框中的非数值变量:视频通道1
一个二个一个一个
是否有代码更短的方法?

dhxwm5r4

dhxwm5r41#

使用dplyr
如果要一次舍入多列:

mydf %>% mutate_at(vars(vnum1, vnum2), funs(round(., 1)))

或者,如果要更改除"vch1"以外的所有列:

mydf %>% mutate_at(vars(-vch1), funs(round(., 1)))

或者,如果要更改所有以"vnum"开头的列:

mydf %>% mutate_at(vars(starts_with("vnum")), funs(round(., 1)))

或者,如果只想更改数值列:

mydf %>% mutate_if(is.numeric, ~round(., 1))

您将获得:

vnum1 vnum2 vch1
1   0.6   0.7    B
2  -1.4   0.5    E
3   0.7   0.9    A
4  -0.3   0.8    C
5  -0.8   0.6    C
htzpubme

htzpubme2#

如果您不介意覆盖原来的mydf

cols <- names(mydf)[1:2]
mydf[,(cols) := round(.SD,1), .SDcols=cols]
mydf

#   vnum1 vnum2 vch1
#1:   0.6   0.7    B
#2:  -1.4   0.5    E
#3:   0.7   0.9    A
#4:  -0.3   0.8    C
#5:  -0.8   0.6    C
cdmah0mi

cdmah0mi3#

dplyr可以在data.table对象上工作!dplyr::mutate(从dplyr 1.0.0主要更新开始)包含了灵活的列规范和函数,用于使用across修改数据。
要指定包含数值数据的所有列:

  • mydf %>% mutate(across(where(is.numeric), ~round(., 1)))

要指定名称以“vnum”开头的所有列:

  • mydf %>% mutate(across(starts_with("vnum"), ~round(., 1)))

它比以前的mutate_if(仍然有效,但已退役)稍微冗长一些,但它与其他可能的规范一致,并允许更多的变化。

旧答案

使用mutate_if的另一个好处是,仅当列为数值时才对其进行舍入
mydf %>% mutate_if(is.numeric, round, 1)

rnmwe5a2

rnmwe5a24#

dplyr 0.8.0开始,funs()soft deprecated。这意味着应该使用list(name = ~f(.))而不是funs(name = f(.))

mydf %>% 
 mutate_at(vars(vnum1, vnum2), list(~ round(., 1)))

  vnum1 vnum2 vch1
1   0.6   0.7    B
2  -1.4   0.5    E
3   0.7   0.9    A
4  -0.3   0.8    C
5  -0.8   0.6    C

或者写成一个简单的lambda函数:

mydf %>% 
 mutate_at(vars(vnum1, vnum2), ~ round(., 1))

然后,从dplyr 1.0.0开始,使用mutate()内部的across()

mydf %>% 
 mutate(across(c(vnum1, vnum2), ~ round(., 1)))

与select helper一起使用,此处选择以“vnum”开头的变量:

mydf %>% 
 mutate(across(starts_with("vnum"), ~ round(., 1)))

或仅选择数值变量:

mydf %>% 
 mutate(across(where(~ is.numeric(.)), ~ round(., 1)))
iezvtpos

iezvtpos5#

require(data.table)

简短澄清的溶液:

mydf[, lapply(.SD, round, 1), vch1]

#   vch1 vnum1 vnum2
#1:    B   0.6   0.7
#2:    E  -1.4   0.5
#3:    A   0.7   0.9
#4:    C  -0.3   0.8
#5:    C  -0.8   0.6

相同,但具有描述性详细信息:

mydf[, lapply(.SD, round, digits = 1), by = vch1]

如果我有许多列,请说:(vnum1,vnum2,vch1,vch2,vbin1,vbin2,vbin3),而我只想取整vnum1和vnum2?
在这种情况下,您可以使用:=运算符和.SDcols =参数来指定要舍入的列:

mydf[, 1:2 := lapply(.SD, round, digits = 1), by = vch1]

如果您需要舍入某些列并从输出中排除其他列,您可以只使用.SDcols =参数同时执行这两项操作:

mydf[, lapply(.SD, round, digits = 1), by = vch1, .SDcols = "vnum1"]

.SDcols =可以提供列名或其编号,
作为名称为.SDcols = "vnum1"或编号为.SDcols = 1的单列
作为名称为.SDcols = c("vnum2", "vnum1")或编号为.SDcols = c(2, 1)的多列
作为名称为.SDcols = vnum1:vnum2或编号为.SDcols = 1:2的列范围

wqlqzqxt

wqlqzqxt6#

如果希望能够返回副本,可以使用函数

职能部门:

auto_round_dt<- function(dt, ndigits=3, return_copy=TRUE){
  dt<- data.table::setDT(dt)
  roundme<- names(sapply(dt, class))[which(sapply(dt, class) == "numeric")]
  if(return_copy == TRUE){
    tmp<- data.table::copy(dt)
    out<- tmp[, (roundme):=round(.SD, ndigits), .SDcols=roundme]
    return(out)
  } else{
    return(dt[, (roundme):=round(.SD, ndigits), .SDcols=roundme])
  }
}

用法

要返回表的副本而不修改原始表:

newdt<- auto_round_dt(dt=mydt, ndigits = 3, return_copy = TRUE)

并在位修改对象:

auto_round_dt(dt=mydt, ndigits = 3, return_copy = FALSE)
  • 注意:* 如果将return_copy=设置为FALSE,则不必将auto_round_dt的结果分配给新的data.table
ujv3wf0j

ujv3wf0j7#

目前最短:

mydf[, vch1, round(mydf[, 1:2], 1)]

#   vnum1 vnum2 vch1
#1:   0.6   0.7    B
#2:  -1.4   0.5    E
#3:   0.7   0.9    A
#4:  -0.3   0.8    C
#5:  -0.8   0.6    C

有趣的方法。但是如果我有很多列,比如:(vnum1,vnum2,vch1,vch2,vbin1,vbin2,vbin3),而我只想舍入vnum1和vnum2?另外,解释一下它是如何工作的也会很有用
它使用data.table的"by ="按舍入列进行分组。
下面的例子是基于这个方法来解决你的第二级任务。
内置数据集:

>dt <- data.table(names = rownames(datasets::ability.cov$cov), datasets::ability.cov$cov)
>dt
#     names general picture  blocks   maze reading   vocab
#1: general  24.641   5.991  33.520  6.023  20.755  29.701
#2: picture   5.991   6.700  18.137  1.782   4.936   7.204
#3:  blocks  33.520  18.137 149.831 19.424  31.430  50.753
#4:    maze   6.023   1.782  19.424 12.711   4.757   9.075
#5: reading  20.755   4.936  31.430  4.757  52.604  66.762
#6:   vocab  29.701   7.204  50.753  9.075  66.762 135.292

短溶液:

> dt_round <- dt[, .SD, by = round(dt[, blocks:maze], 1)]
> dt_round
#   blocks maze   names general picture reading   vocab
#1:   33.5  6.0 general  24.641   5.991  20.755  29.701
#2:   18.1  1.8 picture   5.991   6.700   4.936   7.204
#3:  149.8 19.4  blocks  33.520  18.137  31.430  50.753
#4:   19.4 12.7    maze   6.023   1.782   4.757   9.075
#5:   31.4  4.8 reading  20.755   4.936  52.604  66.762
#6:   50.8  9.1   vocab  29.701   7.204  66.762 135.292

初始列顺序:

> whatever <- setcolorder(dt_round, names(dt))
> whatever
#     names general picture blocks maze reading   vocab
#1: general  24.641   5.991   33.5  6.0  20.755  29.701
#2: picture   5.991   6.700   18.1  1.8   4.936   7.204
#3:  blocks  33.520  18.137  149.8 19.4  31.430  50.753
#4:    maze   6.023   1.782   19.4 12.7   4.757   9.075
#5: reading  20.755   4.936   31.4  4.8  52.604  66.762
#6:   vocab  29.701   7.204   50.8  9.1  66.762 135.292
k3bvogb1

k3bvogb18#

我认为从解决方案来看,Steven Baupre使用dplyr的解决方案是最优雅的,并且可以选择性地应用于 Dataframe 中的不同列,特别是在计算物理中。

library(dplyr)
gasCriticals %>%
  mutate_each(funs(round(., 0)), depth, pres, temp) %>%
  mutate_each(funs(round(., 2)), pres.pr, temp.pr, temp.r) %>%
  mutate_each(funs(round(., 1)), pres.pc, temp.pc)

如您所见,压力和温度将四舍五入到0位小数;假减压和温度至2德克斯;最后,伪临界压力和温度精确到小数点后1位。

nue99wik

nue99wik9#

如果你想要/需要避免特定的data.table约定,你可以在base R中通过转换成一个普通的data.frame来实现(或者如果你从data.frame开始,那么跳过转换步骤)
要转换的列名向量
rCols <- c('vnum1', 'vnum2')
转换为常规数据.frame
mydf1 <- as.data.frame(mydf)
仅覆盖要舍入的特定列
mydf1[, rCols] <- apply(mydf1[, rCols], 2, function(x) round(x, 1))

> mydf1
  vnum1 vnum2 vch1
1   0.6   0.7    B
2  -1.4   0.5    E
3   0.7   0.9    A
4  -0.3   0.8    C
5  -0.8   0.6    C

相关问题