Программа для уменьшения набора данных для соответствия определенным значениям для нескольких переменных - PullRequest
0 голосов
/ 09 февраля 2019

Я довольно отчаянно нуждаюсь в этом, поэтому любая помощь будет очень признательна.

Я использую R, но у меня нет проблем с использованием SAS, если это необходимо.

У меня естьнабор данных с около 100 тыс. записей и 30 переменных.Я хотел бы уменьшить этот набор данных до 1 тыс. Записей, и чтобы средние значения переменных для всего набора данных были как можно ближе к заданному числу для всех 30. Они не должны быть точными, и я понимаю, что это вероятноневозможно.

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

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

Сначала я сделаю несколько поддельных данных с 30 столбцами.Например, я сделаю так, чтобы каждый столбец имел случайные числа со средним значением и sd, соответствующим столбцу.Первый столбец будет иметь среднее значение и sd = 1, второй - среднее значение и sd = 2 и т. Д.

columns = 30
samples = 100000
library(tidyverse)
set.seed(42)
my_data <- data_frame(row = rep(1:samples, times = columns),
                      col = rep(1:columns, each = samples),
                      value = rnorm(samples*columns, mean = col, sd = col)) %>%
                      mutate(col = paste0("c", str_pad(col, 2, pad = "0"))) %>%
                      spread(col, value)

Здесь я подтверждаю, что в каждой строке есть ожидаемое среднее значение и дисперсия:

my_data %>%
  gather(col, value, -row) %>%
  sample_n(10000) %>%    # 10k dots is enough and is quicker to plot than all of them.
  ggplot(aes(col, value)) + 
  geom_point(alpha = 0.1, size = 0.5, color = "gray40") +
  geom_boxplot(fill = NA, outlier.shape = NA) +
  scale_y_continuous(breaks = 60*-2:2)

enter image description here

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

Здесь я вычислю, как далеко каждая точка от среднего значения для своего столбца, затем для каждой строки найдитесредняя RMS абсолютная разница по всем столбцам.Я оставлю верхние 5 в фрейме данных с именем most_typical, а нижние 5 в least_typical.

my_data_how_typical <- my_data %>%
  gather(col, value, -row) %>%     # convert to long format
  group_by(col) %>%                # group by column
  mutate(dist_abs = value - mean(value)) %>%   # calc dist from mean for that col
  ungroup() %>%

  group_by(row) %>%
  summarize(avg_dist_abs = sqrt(mean(dist_abs ^ 2))) 

most_typical <- top_n(my_data_how_typical, 5, wt = -avg_dist_abs)
least_typical <- top_n(my_data_how_typical, 5, wt = avg_dist_abs)

Теперь я построю пятерку самых и наименее типичных по отношению к целому.Зеленые строки most_typical имеют тенденцию оставаться вблизи средних, в то время как least_typical имеют некоторые экстремальные значения.Сохраняя строки с наименьшим отклонением от среднего (вы можете оставить 1000 вместо 5), вы получите список, в котором средние значения будут близки к общему среднему.Но этот список также будет иметь значительно меньшую дисперсию, чем исходные данные, поскольку он намеренно исключает строки с экстремальными значениями.

my_data %>%
  gather(col, value, -row) %>%
  sample_n(10000) %>%
  ggplot(aes(col, value)) + 
  geom_point(alpha = 0.1, size = 0.5, color = "gray40") +
  geom_line(data = least_typical %>% 
              select(row) %>%
              left_join(my_data, by = c("row" = "row")) %>%
              gather(col, value, -row),
            aes(col, value, group = row), color = "red") + 
  geom_line(data = most_typical %>% 
              select(row) %>%
              left_join(my_data, by = c("row" = "row")) %>%
              gather(col, value, -row),
            aes(col, value, group = row), color = "green")

enter image description here

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

0 голосов
/ 09 февраля 2019

Это действительно общий вопрос, но R идеально подходит для этого

. Прочитайте в своем файле (я предполагаю, что он в формате .csv?), Например, my_data <- read.csv("folder/filename.csv", header = TRUE)

. Затем вы можете установить подмножество.фрейм данных примерно такой:

my_data <- my_data[my_data$age >= 25 & my_data$age =< 30 & my_data$gender = "female" & my_data$income > 50000, ]

. Вышеприведенное будет выбирать только женщин в возрасте 25-30 лет с доходом> 50k

Но если вы хотите, чтобы подмножество было основано на средних значениях, вы, безусловно, можете это сделать.тоже.Например,

average_age = mean(my_data$age)

my_data <- my_data[my_data$age >= (average_age - 2) & my_data$age =< (average_age + 2) & my_data$gender = "female" & my_data$income > 50000, ]

Затем можно записать кадр данных обратно в формат csv с помощью

write.csv(my_data, "newfile.csv", row.names=FALSE)
.
...