Функция для одновременного применения уровней факторов и меток к нескольким столбцам - PullRequest
0 голосов
/ 03 мая 2019

У меня есть набор данных опроса, который я импортировал как файл SAS, но он не включал текстовые метки, связанные с числовыми кодами в наборе данных.

Я пытаюсь применить фактор-функцию квсе переменные и затем имеют соответствующие уровни и метки для каждой переменной.

У меня есть основной фрейм данных с фактическими данными, а затем второй фрейм данных с текстовыми метками, соответствующими каждому значению для каждой переменной.

Так, например, имена столбцов переменных в основном наборе данных: A1, B1, C1, D1.Второй кадр данных с метками указан ниже с фиктивным текстом.И для каждой переменной существует различное количество значений, которым требуются текстовые метки.

labels_list <- structure(list(VariableName = c("A1", "A1", "A1", "B1", "B1", 
"B1", "B1", "C1", "C1", "C1", "C1", "C1", "D1", "D1", "D1", "D1", 
"D1", "D1"), Value = c(1L, 2L, 3L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 
4L, 5L, 1L, 2L, 3L, 4L, 5L, 6L), Label = c("Red", "Blue", "Yellow", 
"Up", "Down", "Left", "Right", "Boston", "Atlanta", "Dallas", 
"New York", "Los Angeles", "John", "Jim", "Jake", "Bill", "Bob", 
"Brian")), class = "data.frame", row.names = c(NA, -18L))

Я пытаюсь написать функцию для автоматической маркировки всех факторных переменных.Функция сокращает данные, чтобы убедиться, что все они содержат одинаковые переменные, а затем находятся в абсолютно одинаковом порядке.Я разбил таблицу выше в список с помощью функции split, а затем у каждого имени переменной выше есть свой собственный список, но я сталкиваюсь с ошибкой, когда пытаюсь поместить список в цикл for.

Ниже приведен цикл for, который я написал.

df = основной набор данных

tags_list = список со значением и текстовыми метками

for(i in 1:ncol(df)) {
        for(j in labels_list) {
          if(names(x[,i]) == names(ahs_split[[j]])) {
            x[,i] <- factor(x[,i], levels = c(ahs_split[[j]][[2]]), labels = c(ahs_split[[j]][[3]]))

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

Ответы [ 2 ]

1 голос
/ 03 мая 2019

Если вы не возражаете против некоторых tidyverse глаголов, вы можете изменить свои данные с помощью tidyr::gather. Как только он будет в длинной форме, вы можете объединить данные с поиском кода по имени переменной и преобразовать их обратно в широкий формат. Этот рабочий процесс масштабируется на любое количество столбцов

library(dplyr)
library(tidyr)

labels_list <- structure(list(Variable = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 
2L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L), .Label = c("A1", 
"B1", "C1", "D1"), class = "factor"), Value = c(1L, 2L, 3L, 1L, 
2L, 3L, 4L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 6L), Label = structure(c(15L, 
3L, 18L, 17L, 8L, 12L, 16L, 5L, 1L, 7L, 14L, 13L, 11L, 10L, 9L, 
2L, 4L, 6L), .Label = c("Atlanta", "Bill", "Blue", "Bob", "Boston", 
"Brian", "Dallas", "Down", "Jake", "Jim", "John", "Left", "Los_Angeles", 
"New_York", "Red", "Right", "Up", "Yellow"), class = "factor")), class = "data.frame", row.names = c(NA, 
-18L))

df <- tibble(A1 = rep(1:3,2),
            B1 = c(1:4, 1, 2),
            C1 = c(1:5, 1),
            D1 = 1:6
            )

Для распространения данных потребуется номер строки с итерацией, превышающей Variable, но вы можете удалить ее, когда она больше не нужна.

df %>%
  gather(key = Variable, value = Value) %>%
  left_join(labels_list, by = c("Variable", "Value")) %>%
  select(-Value) %>%
  group_by(Variable) %>%
  mutate(row = row_number()) %>%
  spread(key = Variable, value = Label)
#> Warning: Column `Variable` joining character vector and factor, coercing
#> into character vector
#> # A tibble: 6 x 5
#>     row A1     B1    C1          D1   
#>   <int> <fct>  <fct> <fct>       <fct>
#> 1     1 Red    Up    Boston      John 
#> 2     2 Blue   Down  Atlanta     Jim  
#> 3     3 Yellow Left  Dallas      Jake 
#> 4     4 Red    Right New_York    Bill 
#> 5     5 Blue   Up    Los_Angeles Bob  
#> 6     6 Yellow Down  Boston      Brian
1 голос
/ 03 мая 2019

Одним из способов является преобразование вашего labels_list в список списков:

library(dplyr) # just using dplyr for the pipe %>%, otherwise everything is in base R

# Convert df to list of key:value pairs
labels_list <- labels_list %>%
  split(f = labels_list$VariableName) %>%
  lapply(function(x) list(key = x$Value, value = x$Label))

например:

$A1
$A1$key
[1] 1 2 3

$A1$value
[1] "Red"    "Blue"   "Yellow"

Это может быть сопоставлено с вашим df по кол-вус apply.Это немного странно, поскольку я помещаю имя столбца в качестве первого элемента вектора, переданного функции.

# Map labels onto sample data with factor()
apply(rbind(names(df), df),
  2,
  function(x) factor(x[2:length(x)],
                     levels = labels_list[[x[1]]]$key,
                     labels = labels_list[[x[1]]]$value)) %>%
  as.data.frame()

       A1    B1          C1    D1
1    Blue    Up      Dallas  Jake
2     Red  Down    New York  Jake
3  Yellow  Left      Boston   Jim
4  Yellow Right      Boston  John
5  Yellow  Down Los Angeles  Jake
6     Red  Left     Atlanta  Jake
7    Blue  Down    New York  John
8     Red  Down     Atlanta Brian
9    Blue    Up    New York   Jim
10 Yellow  Down     Atlanta  Bill

Образец данных

set.seed(1724)
df <- data.frame(A1 = floor(runif(10, 1, 4)),
                  B1 = floor(runif(10, 1, 5)),
                  C1 = floor(runif(10, 1, 6)),
                  D1 = floor(runif(10, 1, 7)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...