Добавьте столбец процентов (на строку) в R data.frame элегантным способом - PullRequest
0 голосов
/ 02 мая 2018

Я хочу, чтобы процентные значения были представлены в виде столбца в data.frame. Пример кода работает. Но вопрос заключается в том, является ли это правильным и элегантным R-способом для этого?

> df <- data.frame(addmargins(table(mtcars$gear, useNA="always")))
> df
  Var1 Freq
1    3   15
2    4   12
3    5    5
4 <NA>    0
5  Sum   32

> df$percent <- mapply(function(x) {100 / length(mtcars$gear) * x}, df$Freq)
> df
  Var1 Freq percent
1    3   15  46.875
2    4   12  37.500
3    5    5  15.625
4 <NA>    0   0.000
5  Sum   32 100.000

Для меня нет необходимости ограничивать этот вопрос data.frame.

Ответы [ 4 ]

0 голосов
/ 02 мая 2018

1) prop.table prop.table может быть полезным здесь. Мы используем ave, чтобы применять его отдельно к строкам данных и сводок.

transform(df, Percent = 100 * ave(Freq, Var1 == "Sum", FUN = prop.table))

дает:

  Var1 Freq Percent
1    3   15  46.875
2    4   12  37.500
3    5    5  15.625
4 <NA>    0   0.000
5  Sum   32 100.000

2) пакет таблиц Если целью этого является отображение указанной таблицы, то пакет таблиц хорош. Термины LHS формулы относятся к строкам, а RHS относятся к столбцам.

library(tables)

gear <- factor(mtcars$gear)
tab <- tabular(gear + 1 ~ (n=1) + Percent())

дает:

> tab
gear n  Percent
 3    15  46.88 
 4    12  37.50 
 5     5  15.62 
 All  32 100.00 

Вывод HTML и LaTeX теперь может производиться с использованием html(tab) и latex(tab).

Этот подход больше ориентирован на отображение, но если вы действительно хотите извлечь данные, это можно сделать следующим образом:

m <- as.matrix(tab, format = as.numeric)
dimnames(m) <- list(attr(tab, "rowLabels"), attr(tab, "colLabels"))
0 голосов
/ 02 мая 2018

Я думаю, что добавление полей - плохая практика, поскольку вы смешиваете данные с итогами.

df <- data.frame(table(mtcars$gear, useNA="always"))
df$pct <-df$Freq/sum(df$Freq)*100
df
#>   Var1 Freq    pct
#> 1    3   15 46.875
#> 2    4   12 37.500
#> 3    5    5 15.625
#> 4 <NA>    0  0.000

Или в идиоматическом dplyr коде (не нужно беспокоиться о table):

library(dplyr)
mtcars %>%
  group_by(gear) %>% 
  summarise(Freq=n()) %>% 
  mutate(percent=Freq/sum(Freq)*100)
#> # A tibble: 3 x 3
#>    gear  Freq percent
#>   <dbl> <int>   <dbl>
#> 1     3    15    46.9
#> 2     4    12    37.5
#> 3     5     5    15.6

Обратите внимание, что нет необходимости ungroup после суммирования, поскольку у вас есть только одна переменная группировки, а при суммировании отбрасывается ровно один слой группировки

0 голосов
/ 02 мая 2018

Я думаю, я бы использовал функцию table в base R для этой задачи (используя ее с самого начала):

df <- data.frame(
  "g" = names(table(mtcars$gear)), 
  "f" = as.numeric(table(mtcars$gear)), 
  "p" = as.numeric(100 * (table(mtcars$gear)/length(mtcars$gear)))
)

Это результат:

> df
  g  f      p
1 3 15 46.875
2 4 12 37.500
3 5  5 15.625

Альтернативно добавление процента после создания data.frame для более короткого бита кода:

df <- data.frame(table(mtcars$gear))
df$p <- 100 * (df[,'Freq'] / sum(df[,'Freq']))

Предоставление:

> df
  Var1 Freq      p
1    3   15 46.875
2    4   12 37.500
3    5    5 15.625
0 голосов
/ 02 мая 2018

Я бы рекомендовал решение на основе dplyr::mutate для ясности:

df <- df %>%
    mutate(percent = (Freq/nrow(mtcars)) * 100)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...