Change Value to Percentage of Row in R

change value to percentage of row in R

Seems a fair case for

df/rowSums(df)
# A B C
# A 0.9000000 0.1000000 0.0000000
# B 0.3333333 0.3333333 0.3333333
# C 0.3333333 0.3333333 0.3333333

If you don't want so many digits after the dot set options(digits = 2) or use print(df/rowSums(df), digits = 2) or use round

round(df/rowSums(df), 2)
# A B C
# A 0.90 0.10 0.00
# B 0.33 0.33 0.33
# C 0.33 0.33 0.33

Or as suggested by @akrun

round(prop.table(as.matrix(df1),1),2)

How do I add a new row with percentage change values to an existing dataframe which is in a wide format?

We loop through the columns with lapply (assuming it is a data.frame), get the diff, divide with the first element, round, paste with the % and rbind

rbind(merged, error = lapply(merged, function(x) paste0(100*round(diff(x)/x[1], 2), "%")))
# Jan Feb Mar Apr May Jun
#2017 (A) 1247 1406 1760 2198 1689 2098
#2017 (P) 1259 1187 1649 2090 1682 2056
#error 1% -16% -6% -5% 0% -2%

Or convert to matrix, get the diff, divide by the first row, and paste as above

rbind(merged, error = paste0(100*round(diff(as.matrix(merged))/merged[1,], 2), "%"))

How to convert a row of data to percent? R

Try this:

df[3,-c(1,2)] <- paste0(100*df[3,-c(1,2)],'%')

Month.2020 Jan Feb Mar Apr May Jun Jul
1 1stofMonthCount 4248 4413 4534 4634 4621 4424 3323
2 MonthlyDifference NA 165 121 100 -13 -197 -1101
3 MonthlyPercentChange NA 3.8% 2.7% 2.2% -0.2% -4.3% -24.9%

#Data
df <- structure(list(Month.2020 = c("1stofMonthCount", "MonthlyDifference",
"MonthlyPercentChange"), Jan = c(4248L, NA, NA), Feb = c(4413,
165, 0.038), Mar = c(4534, 121, 0.027), Apr = c(4634, 100, 0.022
), May = c(4621, -13, -0.002), Jun = c(4424, -197, -0.043), Jul = c(3323,
-1101, -0.249)), row.names = c(NA, -3L), class = "data.frame")

R how to calculate 'Percentage of Change' between two rows?

We can use shift from data.table. Convert the 'data.frame' to 'data.table' (setDt(df)), grouped by 'item', we get the "Row" from .I and create the "Percentage_Change" by dividing the "cumVol" by the lag of "cumVol" (got by shift) and multiplying by 100. If needed the grouping column can be removed by assigning (:=) it to NULL.

library(data.table)
setDT(df)[, list(Row = .I, Percentage_Change=round(cumVol*
(100/shift(cumVol)),2)), .(item)][, item := list(NULL)][]
# Row Percentage_Change
#1: 1 NA
#2: 2 500.00
#3: 3 300.00
#4: 4 NA
#5: 5 32.26
#6: 6 120.00
#7: 7 NA
#8: 8 150.00

NOTE: This gives NA for elements where there are no comparison, instead of the Skip.

Row-wise percentage with R

Instead of using a for loop, we can do this with rowSums

df$Fraction <- rowSums(df[2:9], na.rm=TRUE)/8
df$Percent <- 100*df$Fraction

Or as @ColonelBeauvel mentioned, rowMeans will be more compact and appropriate.

df$Fraction <- rowMeans(df[2:9], na.rm=TRUE)

How can I make a new column and data frame with the percentage change from the start of a particular row in R?

One way using dplyr :

library(dplyr)

start <- 3
end <- 9

example %>%
slice(start:end) %>%
mutate(wage_change = (wage - first(wage)) * 100/first(wage))

# wage timestamp wage_change
#1 2500 3 0
#2 2400 4 -4
#3 2300 5 -8
#4 2200 6 -12
#5 2700 7 8
#6 2300 8 -8
#7 2900 9 16

Change a table of totals to a table of percentages based on total row

You can loop through the numeric columns with lapply

col_idx <- sapply(a, is.numeric) # find positions of numeric columns
a[, col_idx] <- lapply(a[, col_idx], function(x) {
ifelse(is.na(x), NA, paste0(x / max(x, na.rm = TRUE) * 100, "%"))
})
a
# Color N_Likes N_Dislikes
#1 Blue 50% 25%
#2 Red 40% 50%
#3 Green 10% 25%
#4 Total 100% 100%

Create a loop with mutate() in order to get percentage values by column

mutate(df, across(everything(), ~.x/sum(.x)))

Btw, when you use mutate, you don't need to refer to the column using $, it's enough to provide column name.

Create variable for percentage change between two values based on group

If you use lag() to define your rate, you will end up with "NA" for every b == 3, and the correct value for b == 7 when you group_by "b". Also, c() is a Primitive function in R and it's best not to use "c" as the name of a variable.

Is this the outcome you're after?

library(tidyverse)
a <- c(3,7,3,7,3,7,3,3,7,3,7,3,7,7)
b <- c("a", "a", "b", "b", "c", "c", "d", "e", "e", "f","f", "g", "g", "h")
d <- c(80, 100, runif(12, min=80, max=100))
df <- data.frame(a,b,d)

df %>% group_by(b) %>%
mutate(rate = 100 * (d - lag(d, default = NA))/lag(d, default = NA))
#> # A tibble: 14 × 4
#> # Groups: b [8]
#> a b d rate
#> <dbl> <chr> <dbl> <dbl>
#> 1 3 a 80 NA
#> 2 7 a 100 25
#> 3 3 b 88.0 NA
#> 4 7 b 91.1 3.54
#> 5 3 c 95.1 NA
#> 6 7 c 82.7 -13.1
#> 7 3 d 92.6 NA
#> 8 3 e 84.1 NA
#> 9 7 e 91.8 9.20
#> 10 3 f 81.9 NA
#> 11 7 f 93.6 14.4
#> 12 3 g 88.7 NA
#> 13 7 g 80.6 -9.11
#> 14 7 h 99.2 NA

Created on 2021-12-20 by the reprex package (v2.0.1)

You can be more flexible with ifelse()'s too, e.g. if you want NA's for cases where you have a single group but zeros for cases where a == 3:

library(tidyverse)
a <- c(3,7,3,7,3,7,3,3,7,3,7,3,7,7)
b <- c("a", "a", "b", "b", "c", "c", "d", "e", "e", "f","f", "g", "g", "h")
d <- c(80, 100, runif(12, min=80, max=100))
df <- data.frame(a,b,d)

df %>% group_by(b) %>%
mutate(group_number = n()) %>%
mutate(rate = ifelse(group_number == 1, NA, ifelse(a == 7, 100 * (d - lag(d, default = NA))/lag(d, default = NA), 0))) %>%
select(-group_number) %>%
ungroup()
#> # A tibble: 14 × 4
#> a b d rate
#> <dbl> <chr> <dbl> <dbl>
#> 1 3 a 80 0
#> 2 7 a 100 25
#> 3 3 b 95.8 0
#> 4 7 b 83.9 -12.5
#> 5 3 c 87.0 0
#> 6 7 c 81.5 -6.26
#> 7 3 d 97.0 NA
#> 8 3 e 99.1 0
#> 9 7 e 82.6 -16.6
#> 10 3 f 82.3 0
#> 11 7 f 96.0 16.7
#> 12 3 g 99.5 0
#> 13 7 g 93.4 -6.09
#> 14 7 h 86.8 NA

Created on 2021-12-20 by the reprex package (v2.0.1)

R Convert a datatable into percentage table columnwise

You can use dplyr::mutate_if() and scales::percent:

x %>% 
mutate_if(endsWith(names(.),"2021"),function(x) x / sum(x)) %>%
mutate_if(endsWith(names(.),"2021"),scales::percent, accuracy = 0.01)

Output:

  class Jan2021 Feb2021
1 A 25.00% 28.57%
2 B 25.00% 42.86%
3 C 50.00% 28.57%


Related Topics



Leave a reply



Submit