Использование cut() и квантиля() для сортировки непрерывных столбцов в R

#r #dplyr

Вопрос:

У меня есть следующий сгенерированный df с возрастом и весом

 df = data.frame(  Age = sample(18:98, 1000, replace = TRUE),  Weight = sample(80:250, 10000, replace = TRUE) )   

Я хочу изменить непрерывные столбцы, создав сегменты на основе квантилей (25%, 50%, 75%. Это можно сделать так:

 gt; quantile(df$Age, probs = c(0.25,0.5,0.75)) 25% 50% 75%   39 58 78  

Однако я хочу использовать функцию cut, используя эти квантили (25%, 50%, 75%)

Как я могу это сделать? Я хочу, чтобы выходные данные преобразовывались во что-то подобное, где любая непрерывная переменная преобразуется в сегменты на основе квантиля (25%, 50%, 75%)

 Age Weight (17.9,44.7] (137,193] (44.7,71.3] (137,193] (71.3,98.1] (79.8,137] (44.7,71.3] (193,250] (17.9,44.7] (79.8,137]  

Комментарии:

1. (1) В вашем коде отсутствует запятая, пожалуйста, проверьте свой собственный код, прежде чем отправлять вопрос. (2) Пожалуйста, используйте set.seed , прежде чем использовать случайные числа, чтобы мы могли попытаться воспроизвести ваши случайные числа (мы не можем). (3) Учитывая , что вы Age должны быть помещены в корзину 39,58,78 , откуда берутся ожидаемые диапазоны Age ?

2. Если вам нужно что-то более мощное , чем просто использование вывода quantile in cut , взгляните на classInt пакет, в котором есть функция classIntervals , которая разбивает непрерывные переменные на ячейки на основе одной из нескольких различных функций.

Ответ №1:

Просто передайте свои квантили в качестве второго аргумента cut , хотя добавьте квантили 0 и 1 , чтобы ваши сокращения имели нижнюю и верхнюю границы. (т. Е. c(0, 0.25, 0.5, 0.75, 1) , которые можно кратко записать как 0:4 / 4 )

Версия Tidyverse

 library(dplyr)  as_tibble(df) %gt;%   mutate(across(everything(), .fn = function(x) cut(x, quantile(x, 0:4/4)))) #gt; # A tibble: 10,000 x 2 #gt; Age Weight  #gt; lt;fctgt; lt;fctgt;  #gt; 1 (18,38] (80,121]  #gt; 2 (78,98] (121,165] #gt; 3 (18,38] (121,165] #gt; 4 (58,78] (208,250] #gt; 5 (58,78] (165,208] #gt; 6 (78,98] (80,121]  #gt; 7 (38,58] (165,208] #gt; 8 (58,78] (80,121]  #gt; 9 (38,58] (165,208] #gt; 10 (58,78] (121,165] #gt; # ... with 9,990 more rows  

Базовая версия R

 df$Age lt;- cut(df$Age, quantile(df$Age, 0:4/4)) df$Weight lt;- cut(df$Weight, quantile(df$Weight, 0:4/4))  

Комментарии:

1. Привет, я на самом деле хочу сделать квантили (0,25, 0,5, 0,75), но когда я это делаю df %gt;% mutate(across(everything(), .fn = function(x) cut(x, quantile(x, probs = c(0.25,0.5,0.75))))) , я получаю значения lt;NAgt;. Вы знаете, почему это так? Кроме того, я вообще не хочу мутировать во всем, потому что я хочу обобщить, чтобы фрейм данных мог иметь не все непрерывные значения.

2. @Eisen если ваш самый низкий разрыв составляет 25% квантиля, то все, что ниже этого, не будет включено и станет NA . Аналогично, все, что превышает 75% — ный центиль, будет NA , если вы установите эти разрывы. Вот почему я предложил добавить 0 и 1 центиль — это разделит ваши данные на 4 правильных квантиля, не исключая самый высокий и самый низкий квартили. Например, квантиль 0-25%, квартиль 25-50%, квартиль 50-75% и квартиль 75-100%

3. @Eisen смотрите мое обновление, чтобы сделать это для каждого столбца в базе R

4. Это круто, но не совсем то, чего я хочу. quantile(df$Age, probs = c(0.25,0.5,0.75)) бы выделить нужный мне пользовательский квантиль.. Пытаюсь понять, как включить его в cut() себя . Таким образом, все, что составляет 25% или меньше, считается 25%, а все, что составляет 75% или больше, считается 75%

5. @Eisen если вы хотите, чтобы каждое наблюдение было помещено в корзину, самые низкие и самые высокие значения наблюдения должны находиться в пределах самого высокого и самого низкого значения breaks . Ввод ваших квантилей сохранит только второй и четвертый квантили. Это то, чего ты хочешь? Если нет, не могли бы вы объяснить, чего вы пытаетесь достичь немного более подробно? Спасибо

Ответ №2:

В моей santoku посылке есть chop_quantiles() :

 library(santoku) df[] lt;- apply(df, 2, chop_quantiles, 0:4/4)  

или еще проще:

 df[] lt;- apply(df, 2, chop_equally, 4)  

Пустые скобки-это трюк, который сохраняется df как data.frame.

Если вам нужны исходные значения в ваших метках, вы можете сделать:

 df[] lt;- apply(df, 2, chop_equally, 4, labels = lbl_intervals(raw = TRUE))