Я работаю с языком программирования R.
Предположим, у меня есть следующий набор данных:
library(ggplot2)
set.seed(42)
heights <- rnorm(100, mean=170, sd=10)
weights <- rnorm(100, mean=65, sd=15)
data <- data.frame(heights, weights)
ggplot(data, aes(x = heights, y = weights)) +
geom_point() +
theme_bw() +
labs(title = "Scatterplot of Heights and Weights",
x = "Height (cm)",
y = "Weight (kg)") +
scale_x_continuous(breaks = seq(floor(min(data$heights)), ceiling(max(data$heights)), by = 5)) +
scale_y_continuous(breaks = seq(floor(min(data$weights)), ceiling(max(data$weights)), by = 5))
Предположим, я смотрю на каждую «коробку», которую можно сделать размером 5х5 — я вручную нарисовал ее поверх исходного сюжета:
Мой вопрос: Меня интересует подсчет количества очков, содержащихся в каждой из этих коробок.
Сначала я определил максимальные границы каждой переменной:
max_height <- max(data$heights)
max_weight <- max(data$weights)
height_breaks <- seq(0, max_height, by=5)
weight_breaks <- seq(0, max_weight, by=5)
Затем, используя функциюexpand.grid(), я попытался создать фрейм данных, содержащий каждое из этих полей, с помощью функцииexpand.grid:
combinations <- expand.grid(height = seq_along(height_breaks)[-length(height_breaks)],
weight = seq_along(weight_breaks)[-length(weight_breaks)])
interval_label <- function(breaks, index) {
paste0("(", breaks[index], "-", breaks[index + 1], ")")
}
combinations$height_interval <- mapply(interval_label, list(height_breaks), combinations$height)
combinations$weight_interval <- mapply(interval_label, list(weight_breaks), combinations$weight)
height_weight_boxes <- combinations[, c("height_interval", "weight_interval")]
Используя дополнительные манипуляции, я создал 4 отдельных столбца для мин/макс каждой переменной:
library(dplyr)
transformed_df <- height_weight_boxes %>%
mutate(
box_number = row_number(),
min_height = as.numeric(sub("\\((.*?)-.*", "\\1", height_interval)),
max_height = as.numeric(sub(".*-(.*)\\)", "\\1", height_interval)),
min_weight = as.numeric(sub("\\((.*?)-.*", "\\1", weight_interval)),
max_weight = as.numeric(sub(".*-(.*)\\)", "\\1", weight_interval))
) %>%
select(box_number, min_height, max_height, min_weight, max_weight)
Теперь это выглядит так:
box_number min_height max_height min_weight max_weight
1 0 5 0 5
2 5 10 0 5
3 10 15 0 5
4 15 20 0 5
5 20 25 0 5
6 25 30 0 5
На последнем этапе я хочу использовать этот опорный кадр (transformed_df) для запроса исходного кадра данных и подсчета количества точек в каждом поле. Логично, что я подумал сделать это, буквально посчитав, сколько точек содержится в границах каждого прямоугольника:
library(dplyr)
count_points_in_box <- function(min_height, max_height, min_weight, max_weight, data) {
data %>%
filter(heights >= min_height, heights < max_height,
weights >= min_weight, weights < max_weight) %>%
nrow()
}
final <- transformed_df %>%
rowwise() %>%
mutate(count = count_points_in_box(min_height, max_height, min_weight, max_weight, data))
В конце я попробовал проверить, соответствует ли количество ящиков исходным данным:
> sum(final$count)
[1] 97
> nrow(data)
[1] 100
Хотя результаты близки, я думаю, что мог сделать что-то не так, поскольку значения не полностью совпадают. Может кто-нибудь, пожалуйста, помогите мне исправить это?





count_points_in_box() включает только точки < max_height и < max_weight, но вы определяете поля, которые заканчиваются на max_height и max_weight. Так что крайности исключены.
Я думаю, что это можно было бы сделать проще, например:
library(tidyverse)
data |>
count(heights = floor(heights/5)*5,
weights = floor(weights/5)*5) |>
complete(heights = seq(0, max(heights), by = 5),
weights = seq(0, max(weights), by = 5),
fill = list(n = 0)) |>
arrange(weights, heights) |>
mutate(box_number = row_number())
Полям здесь было присвоено округление до числа, кратного 5, так что это минимум, а максимум — на 5 больше.
Думаю, мне удалось изменить ваш ответ, добавив больше аргументов DPLYR, чтобы получить его так, как я хотел. Я принял ваш ответ как официальный ответ! :) большое спасибо!
@ Джон Спринг: Большое спасибо за ответ! Можно ли добавить минимальный/максимальный вес и рост для каждой коробки в окончательный ответ?