I have adataframe of counts and I want to add % column after each count column.
df <- data.frame(name= c("Ji", "Ka", "Na", "Po"),
`a(N)`= c(1,4,5,2),
`b(N)`=c(0.5,04,0.8,0.3),
`c(N)`= c(41,49,48,42))
df
name a.N. b.N. c.N.
1 Ji 1 0.5 41
2 Ka 4 4.0 49
3 Na 5 0.8 48
4 Po 2 0.3 42
so I want something like
df <- df %>%
add_column(`a(%)` = df$a.N./sum(df$a.N.), .after= "a.N.") %>%
add_column(`b(%)` = df$b.N./sum(df$b.N.), .after= "b.N.") %>%
add_column(`c(%)` = df$c.N./sum(df$c.N.), .after= "c.N.")
name a.N. a(%) b.N. b(%) c.N. c(%)
1 Ji 1 0.08333333 0.5 0.08928571 41 0.2277778
2 Ka 4 0.33333333 4.0 0.71428571 49 0.2722222
3 Na 5 0.41666667 0.8 0.14285714 48 0.2666667
4 Po 2 0.16666667 0.3 0.05357143 42 0.2333333
My actual dataframe has many more columns so it does not make sense to apply add_column one by one. is there a way to get the percent columns with fewer lines of codes?
CodePudding user response:
We may use across
library(dplyr)
library(stringr)
df %>%
mutate(across(-name, ~ .x/sum(.x),
.names = "{str_remove(.col, fixed('.N.'))}(%)")) %>%
select(name, gtools::mixedsort(names(.)[-1]))
-output
name a.N. a(%) b.N. b(%) c.N. c(%)
1 Ji 1 0.08333333 0.5 0.08928571 41 0.2277778
2 Ka 4 0.33333333 4.0 0.71428571 49 0.2722222
3 Na 5 0.41666667 0.8 0.14285714 48 0.2666667
4 Po 2 0.16666667 0.3 0.05357143 42 0.2333333
CodePudding user response:
Using proportions
.
cbind(df, sapply(df[-1], proportions))[c(1, 2, 5, 3, 6, 4, 7)]
# name a.N. a.N..1 b.N. b.N..1 c.N. c.N..1
# 1 Ji 1 0.08333333 0.5 0.08928571 41 0.2277778
# 2 Ka 4 0.33333333 4.0 0.71428571 49 0.2722222
# 3 Na 5 0.41666667 0.8 0.14285714 48 0.2666667
# 4 Po 2 0.16666667 0.3 0.05357143 42 0.2333333