Логический контроль (чистка) данных

Копия clean_all_the_data_maybe
Очень часто операторы, которые вводят данные и формируют массив, не являются аналитиками и не обращают внимания на содержательное соотношение ответов в пределах каждой из анкет (например, относительно возраста и образования), поскольку процесс ввода данных ими часто доведен до автоматизма. Кроме того, когда оператор недостаточно опытен, внимателен или плохо ознакомился с анкетой или паспортом для ввода данных, в массив могут попасть значения, отличающиеся от соответствующих в анкете. Поэтому непосредственно после ввода данных количественных исследований возникает необходимость логического контроля массива. Под логическим контролем подразумевается проверка данных массива на предмет присутствия в них логических несоответствий. Например, если человек говорит, что его возраст 16 лет и при этом он имеет высшее образование, следует проверить не является ли это ошибкой ввода. В отечественной литературе этап логического контроля данных практически не описан. Его основы и правила написания соответствующего синтаксиса приведены в справке статистического пакета «ОСА for Windows» (справка доступна из самой программы). В зарубежной литературе контролю данных уделяется значительно больше внимания (см., например: [1]). На популярном образовательном портале «Coursera» (https://www.coursera.org/) этой теме посвящен отдельный курс.
Контроль массива данных также называют «чисткой массива». Последнее определение чаще используется в кругу отечественных исследователей, поэтому далее мы будем использовать именно его. Это крайне важный этап управления данными, который позволяет:
  • определить ошибки ввода операторами;
  • привести массив к удобному формату для дальнейшей работы с ним;
  • найти анкеты, которые могли быть фальсифицированы.
Последний пункт не является основной сферой, для которой используется чистка данных. Хотя практика показывает, что некоторые анкеты, которые содержат множество логических противоречий, желательно проверить дополнительно связавшись с респондентом (при наличии его контактов), если ранее эта анкета не попала в выборочный контроль после полевых работ.
Правильно проведенная чистка данных является одним из важных условий их качества. Например, в банк данных Европейского социального исследования (European Social Survey, http://www.europeansocialsurvey.org/) от стран участниц принимаются лишь данные, прошедшие тщательную чистку.
Чистку массива можно условно разделить на техническую и логическую. Техническая чистка используется для: 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