R Генерация значений на основе сравнения предыдущих столбцов - PullRequest
0 голосов
/ 10 мая 2018

Я надеюсь сгенерировать столбец (Мин), который найдет минимум выбранных столбцов имени и извлечет имя столбца в качестве его значения.Ниже приведен пример кадра данных:

          Amy  Abe  Donna  Racheal  Mike     Min       u
          5    34    54     56       23      Amy       0
          43   11    3      33       21      Donna     1
          54   32    21     54       1       Mike      1 
          21   5     43     32       21      Abe       1
          32   21    23     5        32      Racheal   0
          43   2     2      13       45      Abe Donna 1
                            .
                            .
                            .

Столбец u - это просто столбец, который находится в конце набора данных.Набор данных довольно большой, поэтому я пытаюсь найти эффективный метод для генерации столбца Мин.

Код, который я имею в виду:

     MinData <- Data %>% mutate(Min = 
     min(colnames(Data)[1:5]))

Это только извлекает названия столбцов.Что я должен добавить, чтобы столбец мог сравнивать значения в каждой строке и выбирать имя столбца с минимальным значением?

Ответы [ 3 ]

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

Я бы использовал функцию apply, с которой:)

Настройте наш вектор имен

person_names= names(df[,1:5]) #Presumably the column names are the names

1:5 как раз в том случае, если в вашем наборе данных есть другие столбцы, которые вы не хотите рассматривать для минимальной проверки.

Теперь мы можем использовать apply для пользовательской функции, которая возвращает имя из того столбца, который имеет наименьшее значение для каждой строки.

df$Min <- apply(df[,1:5], 1, function(x){person_names[which.min(x)]})

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

which.min просто возвращает номер элемента, где бы ни находился минимум. person_names имеют наши имена в порядке, а which.min возвращает число, которое указывает, какое имя имеет наименьшее значение.

Вы можете сжать все это до однострочного решения, если хотите покончить с переменной person_names.

df$Min <- apply(df[,1:5], 1, function(x){names(df[,1:5])[which.min(x)]})

Если у вас есть только 5 столбцов с именами, отбросьте 1:5, если у вас есть столбцы, где бы то ни было, просто замените их вектором имен или номеров ваших столбцов.

РЕДАКТИРОВАТЬ: Я видел ваш комментарий на другой ответ. Чтобы приспособиться к связям, я изменю пользовательскую функцию, чтобы она проверяла все совпадения с минимальным значением x, а затем вставлял их вместе с некоторым пользовательским разделителем. Я также изменю ваши данные, чтобы Донна и Рейчел связали во втором ряду.

df <- read.table(text = 'Amy  Abe  Donna  Racheal  Mike     Min       u
      5    34    54     56       23      Amy       0
       43   11    3      3       21      Donna     1
       54   32    21     54       1       Mike      1 
       21   5     43     32       21      Abe       1
       32   21    23     5        32      Racheal   0', header = T)

person_names <- names(df[,1:5])

df$Min <- apply(df[,1:5], 1, function(x){paste(person_names[x == min(x)], 
collapse = ", ")})

> df
  Amy Abe Donna Racheal Mike            Min u
1   5  34    54      56   23            Amy 0
2  43  11     3       3   21 Donna, Racheal 1
3  54  32    21      54    1           Mike 1
4  21   5    43      32   21            Abe 1
5  32  21    23       5   32        Racheal 0

Я установил аргумент collapse равным ",", который является произвольно выбранным разделителем. Вы можете настроить его так, чтобы он был просто пробелом "", точкой с запятой или чем угодно.

Опять же, это можно сжать до однострочного ответа, избавившись от отдельной строки для person_names.

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

Ваши исходные данные:

df1 <- structure(list(Amy = c(5L, 43L, 54L, 21L, 32L, 43L), 
                      Abe = c(34L, 11L, 32L, 5L, 21L, 2L), 
                      Donna = c(54L, 3L, 21L, 43L, 23L, 2L), 
                      Racheal = c(56L, 33L, 54L, 32L, 5L, 13L), 
                      Mike = c(23L, 21L, 1L, 21L, 32L, 45L), 
                      u = c(0, 1, 1, 1, 0, 1)), 
                      row.names = c(NA, -6L), 
                      class = "data.frame")

Мы можем использовать tidyr и dplyr для преобразования из широкого в длинный, выполнить вычисления и агрегации, а затем склеить все вместе в конце.

library(dplyr)
library(tidyr)

df1 %>% 
  gather(name, value, -u) %>%                      # convert from wide to long
  group_by(name) %>% 
  mutate(idx = row_number()) %>%                   # add a grouping variable
  ungroup() %>% 
  group_by(idx) %>% 
  mutate(Min = min(value)) %>%                     # calculate min per group (= per row)
  filter(value == Min) %>%                         # keep names with value = Min
  arrange(idx) %>%                                 # order rows as original data
  select(idx, Min = name) %>% 
  summarise(Min = paste(Min, collapse = ",")) %>%  # combine names where Min tied
  ungroup() %>% 
  select(Min) %>% 
  bind_cols(df1, .)                                # combine column Min (names) with 
                                                   # original data

  Amy Abe Donna Racheal Mike u       Min
1   5  34    54      56   23 0       Amy
2  43  11     3      33   21 1     Donna
3  54  32    21      54    1 1      Mike
4  21   5    43      32   21 1       Abe
5  32  21    23       5   32 0   Racheal
6  43   2     2      13   45 1 Abe,Donna
0 голосов
/ 10 мая 2018

Вот как бы я подошел к этому:

library(tidyverse) # we use dplyr and tidyr
Data <- Data %>% 
  mutate(row = 1:length(u)) 

MinData <- Data %>% 
  gather(name, score, -u, -row, -Min) %>% 
  group_by(row) %>%
  summarize(Min2 = paste(name[score == min(score)], collapse = " ")) %>% # called "Min2" to differentiate it from the "Min" column provided in the example.
  left_join(df %>% mutate(row = 1:length(u)), .)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...