Как сделать определенные части фрейма данных в процентах? - PullRequest
0 голосов
/ 10 марта 2020

Вот мой фрейм данных с именем cat_data

print (cat_data)

Metrics                2016    2017    2018    
Number of Cats         100     120      150     
Number Leaving         32      40       65
Number Staying         68      80       85 
Percent of Leavers     .32     .33      .43
Percent of Stayers     .68     .67      .57 

Я хочу преобразовать только строки и 5 в проценты с символом процента.

Вот мой желаемый вывод.

Metrics                2016    2017    2018    
Number of Cats         100     120      150     
Number Leaving         32      40       65
Number Staying         68      80       85 
Percent of Leavers     32%     33%      43%
Percent of Stayers     68%     67%      57% 

Я попробовал это, но не смог заставить его работать.

cat_data[4:5,2:4] <- paste0(cat_data[4:5,2:4] * 100,%)

Может кто-нибудь сказать мне, что мне нужно исправить? благодарю вас.

Ответы [ 5 ]

1 голос
/ 10 марта 2020

это также должно работать

РЕДАКТИРОВАТЬ

Функция вставки требует вектора в качестве ввода, но ваш ввод cat_data[4:5,2:4] является кадром данных.

Функция apply принимает массив в качестве входных данных и выводит вектор.

cat_data[4:5,2:4] <- apply(cat_data[4:5,2:4]*100, 2, function(x) paste0(x, "%"))

Вы берете свой регион фрейма данных и умножаетесь на 100. Это будет входной массив в функции apply , При указании margin = 2 векторизация выполняется по столбцу. затем вы предоставляете функцию, примененную к вектору, которая в данном случае является функцией paste с нужным вам символом %.

0 голосов
/ 10 марта 2020

Вот решение Tidyverse. Трудно понять, какова структура ваших данных, но это не «аккуратно». Я предполагаю, что вы пытаетесь создать сводную таблицу. Я сталкивался с подобными проблемами прежде, когда пытался сделать то же самое. Использование функции mutate_at с case_when является одним из способов, если вы хотите включить знак%, тогда столбцы должны быть символами.

library(dplyr)
library(stringr)

a <- c("Metrics", "Number of Cats", "Number Leaving", "Number Staying", "Percent of Leavers", "Percent of Stayers")
b <- c(2016, 100, 32, 68, .32, .68)
c <- c(2017, 120, 40, 80, .33, .67)
d <- c(2018, 150, 65, 85, .43, .57)

df <- tibble(a = a ,b = b, c = c, d = d)

df %>% 
  mutate_at(.vars = c("b", "c", "d"), .funs = list(~case_when(a %in% c("Percent of    Leavers", "Percent of Stayers") ~ str_c(round(.x*100), " %"),
                                                            TRUE ~ as.character(.x))))

#OUTPUT

  a                  b     c     d    
  <chr>              <chr> <chr> <chr>
1 Metrics            2016  2017  2018 
2 Number of Cats     100   120   150  
3 Number Leaving     32    40    65   
4 Number Staying     68    80    85   
5 Percent of Leavers 32 %  33 %  43 % 
6 Percent of Stayers 68 %  67 %  57 % 
0 голосов
/ 10 марта 2020

Как отметил @Phil в своем ответе, проблема в том, что у вас конфликтующие типы данных. Вам нужно будет преобразовать значения для полей 2016, 2017 и 2018 в символьные. Один из способов - поменять эти поля следующим образом:

# load packages
library(tidyverse)
library(scales)  # package with function for converting decimal to percent

df %>% 
  rowwise() %>% 
  mutate(`2016` = if_else(str_detect(Metrics, "Percent"), scales::percent(`2016`, accuracy = 1), as.character(`2016`))) %>% 
  mutate(`2017` = if_else(str_detect(Metrics, "Percent"), scales::percent(`2017`, accuracy = 1), as.character(`2017`))) %>% 
  mutate(`2018` = if_else(str_detect(Metrics, "Percent"), scales::percent(`2018`, accuracy = 1), as.character(`2018`)))

# # A tibble: 5 x 4
#   Metrics            `2016` `2017` `2018`
#   <fct>              <chr>  <chr>  <chr> 
# 1 Number of Cats     100    120    150   
# 2 Number Leaving     32     40     65    
# 3 Number Staying     68     80     85    
# 4 Percent of Leavers 32%    33%    43%   
# 5 Percent of Stayers 68%    67%    57%  
0 голосов
/ 10 марта 2020

Вы уверены, что хотите сделать это с фреймом данных в R? Форматирование чисел для их представления лучше всего выполнять в конце любого анализа, а делать это внутри фрейма данных - необычный выбор.

Из вопроса, в каком формате находятся ваши столбцы, неясно. c, коэффициент или символ?

Не зная этого, лучший способ сделать это в базе R - это, вероятно, использовать lapply в каждом столбце, преобразовать его в число c с помощью символа, умножить любой значение меньше, чем один на 100, преобразуйте весь столбец в символьный формат, а затем добавьте знак процента к преобразованным числам.

Однако это приведет к преобразованию всего фрейма данных в символьные строки, поэтому больше не сможет вычислять их без дальнейшего преобразования. Возможно, было бы лучше переосмыслить, как вы собираетесь использовать или представлять данные.

Тем не менее, вот реализация вышеупомянутого метода:

as.data.frame(lapply(df, function(x)
{
  if(!any(grepl("Number", x))) 
  {
    x <- as.numeric(as.character(x))
    s <- which(x < 1)
    x[s] <- x[s] * 100 
    x <- as.character(x) 
    x[s] <- paste0(x[s], "%")
  }
  return(x)
}))
#>             Metrics X2016 X2017 X2018
#>1     Number of Cats   100   120   150
#>2     Number Leaving    32    40    65
#>3     Number Staying    68    80    85
#>4 Percent of Leavers   32%   33%   43%
#>5 Percent of Stayers   68%   67%   57%
0 голосов
/ 10 марта 2020

Ваш код не работает, потому что paste0() векторизуется, а ваша таблица не настроена должным образом для обеспечения векторизации.

Это немного неуклюже, но вы можете сделать это:

cat_data <- tibble::tribble(
  ~"Metrics", ~"2016", ~"2017", ~"2018",
  "Number of Cats", 100, 120,  150,
  "Number Leaving", 32, 40, 65,
  "Number Staying", 68, 80, 85,
  "Percent of Leavers", .32 , .33, .43,
  "Percent of Stayers", .68, .67, .57) # create data

percent_data <- cat_data[4:5,] # separate percent rows
cat_data <- cat_data[-(4:5),] # remove percent rows

for (i in 2:4) { # apply the desired transformation to each column
  percent_data[[i]] <- paste0(percent_data[[i]] * 100, "%")
}

cat_data <- rbind(cat_data, percent_data) # bind them back
cat_data

# A tibble: 5 x 4
  Metrics            `2016` `2017` `2018`
  <chr>              <chr>  <chr>  <chr> 
1 Number of Cats     100    120    150   
2 Number Leaving     32     40     65    
3 Number Staying     68     80     85    
4 Percent of Leavers 32%    33%    43%   
5 Percent of Stayers 68%    67%    57%  
...