在R中舍入选定的data.table列

rns*_*nso 34 r data.table

我有以下数据和代码来舍入此data.table的选定列:

> dput(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),]
Error in Math.data.frame(list(vnum1 = c(0.590165705411504, -1.39939534199836,  : 
  non-numeric variable in data frame: vch1

> cbind(mydf[,3,with=F], mydf[,1:2,with=F][,round(.SD,1),])
   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
Run Code Online (Sandbox Code Playgroud)

有更好的方法(更短的代码)?谢谢你的帮助.

Ste*_*pré 48

运用 dplyr

如果要一次舍入多个列:

mydf %>% mutate_at(vars(vnum1, vnum2), funs(round(., 1)))
Run Code Online (Sandbox Code Playgroud)

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

mydf %>% mutate_at(vars(-vch1), funs(round(., 1)))
Run Code Online (Sandbox Code Playgroud)

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

mydf %>% mutate_at(vars(starts_with("vnum")), funs(round(., 1)))
Run Code Online (Sandbox Code Playgroud)

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

mydf %>% mutate_if(is.numeric, ~round(., 1))
Run Code Online (Sandbox Code Playgroud)

你得到:

  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
Run Code Online (Sandbox Code Playgroud)

  • 警告:“从 dplyr 0.8.0 开始,funs() 已被软弃用” (2认同)

the*_*ail 28

如果你不介意覆盖原文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
Run Code Online (Sandbox Code Playgroud)

  • 可以缩短为:`mydf[,(cols) := round(.SD,1), .SDcols=1:2]` (2认同)

Art*_*Yip 25

鉴于dplyr::mutate_each已弃用,mutate_if只有在数字为圆时才使用舍入列的额外好处

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


Geo*_*sky 7

需要(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
Run Code Online (Sandbox Code Playgroud)

相同,但有描述性的细节:

mydf[, lapply(.SD, round, digits = 1), by = vch1]
Run Code Online (Sandbox Code Playgroud)

如果我有很多列,请说:(vnum1,vnum2,vch1,vch2,vbin1,vbin2,vbin3),我想只舍入vnum1和vnum2?

在这种情况下,您可以使用:=运算符和.SDcols =参数来指定要舍入的列:

mydf[, 1:2 := lapply(.SD, round, digits = 1), by = vch1]
Run Code Online (Sandbox Code Playgroud)

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

mydf[, lapply(.SD, round, digits = 1), by = vch1, .SDcols = "vnum1"]
Run Code Online (Sandbox Code Playgroud)

.SDcols =可以提供列名称或它的编号,
作为单个列的名称.SDcols = "vnum1"或数字.SDcols = 1
作为多列的名称.SDcols = c("vnum2", "vnum1")或数字.SDcols = c(2, 1)
作为列按名称.SDcols = vnum1:vnum2或数字.SDcols = 1:2


tmf*_*mnk 5

截至dplyr0.8.0,funs()软弃用。这意味着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
Run Code Online (Sandbox Code Playgroud)

但是,在这种情况下,不需要使用任何功能(因为只有一个功能),@ Arthur Yip的方法可以应用于所有方案。

通过其名称显式选择列:

mydf %>% 
 mutate_at(vars(vnum1, vnum2), round, 1)
Run Code Online (Sandbox Code Playgroud)

或选择以开头的列vnum

mydf %>% 
 mutate_at(vars(starts_with("vnum")), round, 1)
Run Code Online (Sandbox Code Playgroud)

或选择包含vnum以下内容的列:

mydf %>% 
 mutate_at(vars(contains("vnum")), round, 1)
Run Code Online (Sandbox Code Playgroud)

或选择匹配的列vnum

mydf %>% 
 mutate_at(vars(matches("vnum")), round, 1)
Run Code Online (Sandbox Code Playgroud)

或按名称明确排除列:

mydf %>% 
 mutate_at(vars(-vch1), round, 1)
Run Code Online (Sandbox Code Playgroud)

或排除匹配的列vch

mydf %>% 
 mutate_at(vars(-matches("vch")), round, 1)
Run Code Online (Sandbox Code Playgroud)

或选择前两列:

mydf %>% 
 mutate_at(1:2, round, 1)
Run Code Online (Sandbox Code Playgroud)

或排除第三列:

mydf %>% 
 mutate_at(-3, round, 1)
Run Code Online (Sandbox Code Playgroud)