Логический контроль (чистка) данных
10/07/15 00:23 Относится к категории: Эмпирическая социология | Анализ данных | R | Социологическое образование
Очень часто операторы, которые вводят данные и формируют массив, не являются аналитиками и не обращают внимания на содержательное соотношение ответов в пределах каждой из анкет (например, относительно возраста и образования), поскольку процесс ввода данных ими часто доведен до автоматизма. Кроме того, когда оператор недостаточно опытен, внимателен или плохо ознакомился с анкетой или паспортом для ввода данных, в массив могут попасть значения, отличающиеся от соответствующих в анкете. Поэтому непосредственно после ввода данных количественных исследований возникает необходимость логического контроля массива. Под логическим контролем подразумевается проверка данных массива на предмет присутствия в них логических несоответствий. Например, если человек говорит, что его возраст 16 лет и при этом он имеет высшее образование, следует проверить не является ли это ошибкой ввода. В отечественной литературе этап логического контроля данных практически не описан. Его основы и правила написания соответствующего синтаксиса приведены в справке статистического пакета «ОСА for Windows» (справка доступна из самой программы). В зарубежной литературе контролю данных уделяется значительно больше внимания (см., например: [1]). На популярном образовательном портале «Coursera» (https://www.coursera.org/) этой теме посвящен отдельный курс.
Контроль массива данных также называют «чисткой массива». Последнее определение чаще используется в кругу отечественных исследователей, поэтому далее мы будем использовать именно его. Это крайне важный этап управления данными, который позволяет:
Контроль массива данных также называют «чисткой массива». Последнее определение чаще используется в кругу отечественных исследователей, поэтому далее мы будем использовать именно его. Это крайне важный этап управления данными, который позволяет:
- определить ошибки ввода операторами;
- привести массив к удобному формату для дальнейшей работы с ним;
- найти анкеты, которые могли быть фальсифицированы.
Правильно проведенная чистка данных является одним из важных условий их качества. Например, в банк данных Европейского социального исследования (European Social Survey, http://www.europeansocialsurvey.org/) от стран участниц принимаются лишь данные, прошедшие тщательную чистку.
Чистку массива можно условно разделить на техническую и логическую. Техническая чистка используется для: 1) проверки вопросов с множественными альтернативами: контроль максимального / минимального количества выбранных вариантов ответа (на тот случай если количество категорий, которые необходимо выбрать установлено точно или ограничено определенным количеством); 2) проверка для вопросов этого же типа, не выбран ли вариант «Ничего из перечисленного» вместе с другими вариантами ответа; 3) правильных переходов после вопросов-фильтров.
Логическая чистка – более творческая. Если в случае технической чистки исследователь может руководствоваться исключительно требованиями к заполнению анкеты, то при логической ему необходимо подключить свое воображение и знания с целью определения тех конфигураций ответов, которые в логическом смысле являются противоречивыми. Нахождение таких ситуаций обычно указывает на ошибки ввода данных или фальсификацию анкет.
В первую очередь аналитику необходимо проверить отсутствие дублей анкет в массиве, то есть ввод одной анкеты два и более раза. Самый простой способ - это построение одномерного распределения по ключевому признаку (как правило это уникальный номер анкеты). Если по нему обнаружены дубли, следует удостовериться, что ответы на вопросы также идентичны, и удалить дублирующую анкету. Для проверки идентичности ответов (не по ключевому признаку, а по содержанию всех ответов) можно использовать следующий синтаксис:
Сначала преобразуем массив, требующий проверки, в матрицу «takeData» и создаем пустой вектор «shortlist». Далее с помощью цикла for() для каждой строки матрицы с помощью функции apply() проверяем ее идентичность со всеми строками (в том числе и с самой собой) этой же матрицы, а результаты записываем в виде логического вектора «check». В данном случае «-70» указывает на то, что необходимо исключить переменную с семидесятым индексом, которая является ключевым признаком (в противном случае каждое наблюдение будет уникальным). Если количество значений TRUE превышает единицу (то есть содержание строки совпадает не только само с собой, но и содержанием, по крайней мере, еще одной строки), то в вектор «shortlist» записываются номера соответствующих строк за исключением той, которая проверяется в данный момент. И если номера текущей строки нет в «shortlist», то с помощью функции cat() выводится результат, представляющий собой номер проверяемой в данный момент строки и тех строк, которые ее дублируют.
Если же ответы на вопросы с одинаковыми номерами не идентичны, тогда ошибка ввода была в номере анкеты, и каждой анкете надо присвоить уникальный номер. После этого можно переходить непосредственно к чистке данных, в процессе которой аналитик формулирует ряд логических условий программными средствами. Результатом их проверки будет список с номерами анкет, в которых обнаружены логические противоречия. Когда в распоряжении исследователя находятся бумажные анкеты, он может обратиться к ним, чтобы понять, совершены ли соответствующие ошибки в процессе ввода данных оператором, и при необходимости исправить их. Также можно определить, не выделяются ли отдельные анкеты среди других по количеству ошибок. При наличии последних их можно проконтролировать, связавшись с респондентом. Кроме того стоит проверить и другие анкеты соответствующего интервьюера.
Рассмотрим примеры технической (примеры 1 и 2) и логической (примеры 3 и 4) чистки.
Пример 1. Вопрос с множественными альтернативами про членство в общественных и политических организациях не может одновременно содержать ответ про членство в одной или более организации(-ях) из списка и вариант ответа «Не принадлежу ни к одной». Для проверки можно использовать следующий набор команд:
finalUSind$b4_sum <- rowSums(finalUSind[15:27])
falserows_b4 <- finalUSind$b4_sum > 0 & finalUSind$b4_14 == 1
wrong_b4 <- which(falserows_b4 == T)
Сначала находится общее количество выборов общественных и политических организаций по каждому респонденту, которое записывается в переменную «b4_sum». Для этого используется функция rowSums(), относящаяся к категории функций (наряду с colSums(), rowMeans(), colMeans()), предназначенных для агрегирования информации в строках или столбцах массива. Далее с помощью двух логических условий, соответствующих описанным выше условиям, создается логический вектор «falserows_b4», в котором значения TRUE соответствуют тем строкам массива, в которых выявлено логическое противоречие, а FALSE - тем, в которых не выявлено. После этого с помощью функции which() создается вектор «wrong_b4», содержащий номера только тех строк, в которых выявлено логическое противоречие. В завершении можно обратиться к этим номерам и проверить соответствующие анкеты.
Пример 2. В мониторинге «Украинское общество» отсутствуют вопросы-фильтры. В то же время, при необходимости проверить правильность переходов после вопросов-фильтров, следует прописать соответствующие условия. Допустим, что респонденту, который отвечает, что не хотел бы уезжать из населенного пункта, в котором он живет, не должен задаваться вопрос о возможном направлении переезда. Суть команд такая же, как и в предыдущем случае (аналогично для третьего и четвертого примеров):
falserows_i5 <- finalUSind$i4 == "Ні" & !is.na(finalUSind$i5)
wrong_i5 <- which(falserows_i5 == T)
Пример 3. Количество людей, с которыми респондент проживает в одной комнате, не должно быть больше количества людей, с которыми он проживает в одной квартире (доме).
falserows_k7 <- finalUSind$k7 > finalUSind$k6
wrong_k7 <- which(falserows_k7 == T)
Пример 4. Если в вопросе о виде занятости отмечен ответ «Не работаю и не имею никаких источников дохода», то в вопросе о размере заработной платы за последний месяц должен быть ноль.
false_l3 <- finalUSind$n1 == "Не працюю i…» & finalUSind$l3 > 0
wrong_l3 <- which(false_l3 == T)
Чем больше переменных используется в логических условиях, тем выше вероятность нахождения ошибки ввода или выявления фальсифицированной анкеты. В то же время стоит иметь в виду, что некоторые условия логической чистки не могут прямо говорить об ошибочном, неправильном ответе. В последнем примере респондент мог сказать о своём последнем личном доходе, а не о доходе за последний месяц, или только в данном месяце он стал безработным без каких-либо источников дохода, а прошлом месяце имел доход.
Кроме того, не стоит увлекаться такими «слабыми» условиями, как, например, «Люди с высшим образованием не могут быть полностью неудовлетворенными уровнем своего образования» или «Украинцы по национальности не могут исповедовать ислам». Хотя это и нестандартные ситуации, но вполне вероятные. Также следует придерживаться разумных пределов в количестве логических условий. Присутствие малой доли нелогичности в анкете вполне допустимо. Бывают ситуации, когда некоторые оценочные суждения в начале и в конце анкеты могут не совпадать, что может свидетельствовать о неопределенности мнения респондента по данному вопросу.
После реализации синтаксиса и получения перечня выявленных ошибок возможны два варианта дальнейших действий: 1) обращение к бумажным анкетам по их номеру и проверка правильности введенных данных (то есть сопоставление значений в массиве и анкете), исправление значений по необходимости; 2) работа исключительно с массивом данных.
Первый вариант является более предпочтительным, но тогда чистка занимает значительно больше времени. Второй вариант – менее затратный по времени, но в этом случае исследователю приходиться принимать решение об изменении значений в переменных, содержащих несоответствия, «на свой страх и риск».
В завершении этой части статьи мы приводим синтаксис, который структурирует всю проделанную перед этим работу и приводит результаты к более удобному формату:
Сначала создается список «itogi» с информацией про пропуски, полученная в предыдущих четырех примерах. Далее создается вектор «inorder», в котором фиксируется порядок анкет в зависимости от количества найденых в них логических несоответствий (по убыванию). После этого создается еще один список «rawresult», в котором с помощью цикла for() и функции lapply() для каждой анкеты фиксируется наличие или отсутствие логического несоответствия в отношении каждой проверки. Наконец создается последний список «letsee», в котором для каждой анкеты остаются только те результаты, в которых зафиксированно наличие логических несоответствий. Этот финальный список может быть использован в качестве руководства для поиска и обработки анкет, попадающих под условия проверки.
Чистку массива можно условно разделить на техническую и логическую. Техническая чистка используется для: 1) проверки вопросов с множественными альтернативами: контроль максимального / минимального количества выбранных вариантов ответа (на тот случай если количество категорий, которые необходимо выбрать установлено точно или ограничено определенным количеством); 2) проверка для вопросов этого же типа, не выбран ли вариант «Ничего из перечисленного» вместе с другими вариантами ответа; 3) правильных переходов после вопросов-фильтров.
Логическая чистка – более творческая. Если в случае технической чистки исследователь может руководствоваться исключительно требованиями к заполнению анкеты, то при логической ему необходимо подключить свое воображение и знания с целью определения тех конфигураций ответов, которые в логическом смысле являются противоречивыми. Нахождение таких ситуаций обычно указывает на ошибки ввода данных или фальсификацию анкет.
В первую очередь аналитику необходимо проверить отсутствие дублей анкет в массиве, то есть ввод одной анкеты два и более раза. Самый простой способ - это построение одномерного распределения по ключевому признаку (как правило это уникальный номер анкеты). Если по нему обнаружены дубли, следует удостовериться, что ответы на вопросы также идентичны, и удалить дублирующую анкету. Для проверки идентичности ответов (не по ключевому признаку, а по содержанию всех ответов) можно использовать следующий синтаксис:
for (i in 1:nrow(takeData)) { check <- apply(takeData[,-70], 1, function(x) identical(x,takeData[i,-70])) if (table(check)["TRUE"] > 1) { shortlist <- c(shortlist, which(check == T)[which(check == T) != i]) if (!i%in%shortlist) cat("строка",takeData[i,"keyVar"],":", which(check == T)[which(check == T) != i], "\n") } }
Сначала преобразуем массив, требующий проверки, в матрицу «takeData» и создаем пустой вектор «shortlist». Далее с помощью цикла for() для каждой строки матрицы с помощью функции apply() проверяем ее идентичность со всеми строками (в том числе и с самой собой) этой же матрицы, а результаты записываем в виде логического вектора «check». В данном случае «-70» указывает на то, что необходимо исключить переменную с семидесятым индексом, которая является ключевым признаком (в противном случае каждое наблюдение будет уникальным). Если количество значений TRUE превышает единицу (то есть содержание строки совпадает не только само с собой, но и содержанием, по крайней мере, еще одной строки), то в вектор «shortlist» записываются номера соответствующих строк за исключением той, которая проверяется в данный момент. И если номера текущей строки нет в «shortlist», то с помощью функции cat() выводится результат, представляющий собой номер проверяемой в данный момент строки и тех строк, которые ее дублируют.
Если же ответы на вопросы с одинаковыми номерами не идентичны, тогда ошибка ввода была в номере анкеты, и каждой анкете надо присвоить уникальный номер. После этого можно переходить непосредственно к чистке данных, в процессе которой аналитик формулирует ряд логических условий программными средствами. Результатом их проверки будет список с номерами анкет, в которых обнаружены логические противоречия. Когда в распоряжении исследователя находятся бумажные анкеты, он может обратиться к ним, чтобы понять, совершены ли соответствующие ошибки в процессе ввода данных оператором, и при необходимости исправить их. Также можно определить, не выделяются ли отдельные анкеты среди других по количеству ошибок. При наличии последних их можно проконтролировать, связавшись с респондентом. Кроме того стоит проверить и другие анкеты соответствующего интервьюера.
Рассмотрим примеры технической (примеры 1 и 2) и логической (примеры 3 и 4) чистки.
Пример 1. Вопрос с множественными альтернативами про членство в общественных и политических организациях не может одновременно содержать ответ про членство в одной или более организации(-ях) из списка и вариант ответа «Не принадлежу ни к одной». Для проверки можно использовать следующий набор команд:
finalUSind$b4_sum <- rowSums(finalUSind[15:27])
falserows_b4 <- finalUSind$b4_sum > 0 & finalUSind$b4_14 == 1
wrong_b4 <- which(falserows_b4 == T)
Сначала находится общее количество выборов общественных и политических организаций по каждому респонденту, которое записывается в переменную «b4_sum». Для этого используется функция rowSums(), относящаяся к категории функций (наряду с colSums(), rowMeans(), colMeans()), предназначенных для агрегирования информации в строках или столбцах массива. Далее с помощью двух логических условий, соответствующих описанным выше условиям, создается логический вектор «falserows_b4», в котором значения TRUE соответствуют тем строкам массива, в которых выявлено логическое противоречие, а FALSE - тем, в которых не выявлено. После этого с помощью функции which() создается вектор «wrong_b4», содержащий номера только тех строк, в которых выявлено логическое противоречие. В завершении можно обратиться к этим номерам и проверить соответствующие анкеты.
Пример 2. В мониторинге «Украинское общество» отсутствуют вопросы-фильтры. В то же время, при необходимости проверить правильность переходов после вопросов-фильтров, следует прописать соответствующие условия. Допустим, что респонденту, который отвечает, что не хотел бы уезжать из населенного пункта, в котором он живет, не должен задаваться вопрос о возможном направлении переезда. Суть команд такая же, как и в предыдущем случае (аналогично для третьего и четвертого примеров):
falserows_i5 <- finalUSind$i4 == "Ні" & !is.na(finalUSind$i5)
wrong_i5 <- which(falserows_i5 == T)
Пример 3. Количество людей, с которыми респондент проживает в одной комнате, не должно быть больше количества людей, с которыми он проживает в одной квартире (доме).
falserows_k7 <- finalUSind$k7 > finalUSind$k6
wrong_k7 <- which(falserows_k7 == T)
Пример 4. Если в вопросе о виде занятости отмечен ответ «Не работаю и не имею никаких источников дохода», то в вопросе о размере заработной платы за последний месяц должен быть ноль.
false_l3 <- finalUSind$n1 == "Не працюю i…» & finalUSind$l3 > 0
wrong_l3 <- which(false_l3 == T)
Чем больше переменных используется в логических условиях, тем выше вероятность нахождения ошибки ввода или выявления фальсифицированной анкеты. В то же время стоит иметь в виду, что некоторые условия логической чистки не могут прямо говорить об ошибочном, неправильном ответе. В последнем примере респондент мог сказать о своём последнем личном доходе, а не о доходе за последний месяц, или только в данном месяце он стал безработным без каких-либо источников дохода, а прошлом месяце имел доход.
Кроме того, не стоит увлекаться такими «слабыми» условиями, как, например, «Люди с высшим образованием не могут быть полностью неудовлетворенными уровнем своего образования» или «Украинцы по национальности не могут исповедовать ислам». Хотя это и нестандартные ситуации, но вполне вероятные. Также следует придерживаться разумных пределов в количестве логических условий. Присутствие малой доли нелогичности в анкете вполне допустимо. Бывают ситуации, когда некоторые оценочные суждения в начале и в конце анкеты могут не совпадать, что может свидетельствовать о неопределенности мнения респондента по данному вопросу.
После реализации синтаксиса и получения перечня выявленных ошибок возможны два варианта дальнейших действий: 1) обращение к бумажным анкетам по их номеру и проверка правильности введенных данных (то есть сопоставление значений в массиве и анкете), исправление значений по необходимости; 2) работа исключительно с массивом данных.
Первый вариант является более предпочтительным, но тогда чистка занимает значительно больше времени. Второй вариант – менее затратный по времени, но в этом случае исследователю приходиться принимать решение об изменении значений в переменных, содержащих несоответствия, «на свой страх и риск».
В завершении этой части статьи мы приводим синтаксис, который структурирует всю проделанную перед этим работу и приводит результаты к более удобному формату:
itogi <- list("ошибка в b4" = wrong_b4, "ошибка в i5" = wrong_i5, "ошибка в k7" = wrong_k7, "ошибка в l3" = wrong_l3) inorder <- names(sort(table(unlist(itogi)),decreasing = T)) rawresult <- list() for (i in inorder) { rawresult[[i]] <- lapply(itogi, function(x) as.numeric(i) %in% x) } letsee <- lapply(rawresult, function(x) x[x == T])
Сначала создается список «itogi» с информацией про пропуски, полученная в предыдущих четырех примерах. Далее создается вектор «inorder», в котором фиксируется порядок анкет в зависимости от количества найденых в них логических несоответствий (по убыванию). После этого создается еще один список «rawresult», в котором с помощью цикла for() и функции lapply() для каждой анкеты фиксируется наличие или отсутствие логического несоответствия в отношении каждой проверки. Наконец создается последний список «letsee», в котором для каждой анкеты остаются только те результаты, в которых зафиксированно наличие логических несоответствий. Этот финальный список может быть использован в качестве руководства для поиска и обработки анкет, попадающих под условия проверки.
blog comments powered by Disqus