Резюме
Во многих научных приложениях важно отслеживать различные виды недостающих значений. Отсутствует ли значение «еженедельный доход от основной работы», потому что у человека нет работы, или потому что у него есть работа, но он отказался отвечать?
- Сохранение всех пропущенных значений как
NA
или NaN
теряет эту информацию.
- Хранение пропущенных меток значений (например, «отсутствует, потому что нет работы», «отсутствует, потому что отказался отвечать») в отдельном столбце означает, что исследователь должен отслеживать два столбца для каждой выполняемой им операции - такие как групповой, переименование и т. д. Это создает бесконечные возможности для ошибок и ошибок.
- Хранение меток отсутствующих значений в том же столбце (например, в виде отрицательных чисел, как в примере ниже, или очень больших чисел, таких как 99999) означает, что исследователь должен вручную отслеживать, как метки отсутствующих значений кодируется для каждого столбца и создает много других возможностей для ошибок (например, забывая, что столбец содержит пропущенные значения, и вместо использования правильной маски берется среднее значение).
Очень легко решить эту проблему в Stata
(см. Ниже), используя тип данных, в котором хранятся как числовые значения, так и метки пропущенных значений, а также функции, которые знают, как обрабатывать этот тип данных. Это очень производительность (тип данных остается числовым, а не строковым или смешанным - подумайте о типах данных NumPy, за исключением того, что вместо NaN
у нас есть NaN1
, NaN2
и т. Д.) Что такое лучший способ достижения чего-то подобного в пандах?
Примечание: я экономист, но это также невероятно распространенный рабочий процесс для политологов, эпидемиологов и т. Д. - всех, кто имеет дело с данными опросов. В этом контексте аналитик знает, что такое пропущенные значения с помощью кодовой книги, действительно заботится о том, чтобы отслеживать их, и имеет сотни или тысячи столбцов для работы - поэтому, действительно, нужен автоматический способ их отслеживания.
Мотивация / контекст
При работе с любыми данными опроса очень часто бывает несколько видов пропущенных данных.
Вот минимальный пример из правительственной анкеты, используемой для получения официальной статистики занятости:
- [Q1] У вас есть работа?
- [Q2] [Если Q1 = Да] Каков ваш еженедельный доход от этой работы?
Вышеуказанное встречается практически во всех государственных обследованиях рабочей силы в мире (например, Обследование рабочей силы в Великобритании , Текущее обследование населения США и т. Д.).
Теперь, для данного респондента, если [Q2] отсутствует, возможно, что (1) они ответили «Нет» на [Q1], и, таким образом, не отвечали требованиям , чтобы их спросили [Q2], или что (2) они ответили «Да» на [Q1], но отказались ответить [Q2] (возможно, потому, что их смутило, сколько / мало они зарабатывают или потому, что они не знали).
Как исследователь, для меня очень важно, произошло ли это (1) или (2). Предположим, моя работа состоит в том, чтобы сообщать о среднем еженедельном доходе работников в Соединенных Штатах. Если в этом столбце [Q2] много пропущенных значений, но все они помечены как «отсутствующие, поскольку респондент ответил« нет »на [Q1]», то я могу с уверенностью взять среднее значение [Q2] - это действительно среднее еженедельный доход людей на работе. (Все пропущенные значения - это люди, у которых не было работы.)
С другой стороны, если все пропущенные значения [Q2] помечены как «отсутствующие, поскольку респондент задал этот вопрос, но отказался отвечать», то я не могу просто сообщить среднее значение [Q2] как средний недельный доход работников , Мне нужно сделать оговорки вокруг моих результатов. Мне нужно проанализировать, какие люди не отвечают (случайно ли они пропадают или люди с более высокими доходами чаще отказываются, например, искажать мои результаты?). Возможно, я попытаюсь вменять пропущенные значения и т. Д.
Theпроблема
Поскольку эти «причины пропажи» очень важны, государственные статистические агентства будут кодировать различные причины в столбце:
![enter image description here](https://i.stack.imgur.com/DyCZo.png)
Таким образом, столбец, содержащий ответы на [Q2] выше, может содержать значения [1500, -8, 10000, -2, 3000, -1, 6400].
В этом случае «1500», «10000» и т. Д. Являются «верными» ответами на [Q2] (еженедельный доход в размере 1500 долларов США, еженедельный доход в размере 10 000 долларов США и т. Д.); тогда как «-8» означает, что они не имели права отвечать (потому что они ответили «Нет» на [Q1]), «-2» означает, что они имели право отвечать, но отказались сделать это, и т. д.
Теперь, очевидно, если я возьму среднее значение этого столбца, я получу что-то бессмысленное.
С другой стороны, если я просто заменю все отрицательные значения на NaN
, тогда я могу взять среднее значение - но я потерял всю эту ценную информацию о том, почему значения отсутствуют. Например, я могу захотеть иметь функцию, которая принимает любой столбец и отчеты, для этого столбца такие статистические данные, как среднее значение и медиана, число приемлемых наблюдений (т. Е. Все, кроме значения = -8), и процент тех , которые не пропали без вести.
Отлично работает в Stata
Выполнить это в Stata
чрезвычайно легко. Stata
имеет 27 пропущенных числовых категорий: от .a до .z. (Подробнее здесь .) Могу написать:
replace weekly_income = .a if weekly_income == -1
replace weekly_income = .b if weekly_income == -8
и т. Д.
Тогда (в псевдокоде) я могу написать
stats weekly_income if weekly_income!=.b
При сообщении среднего значения, Stata
автоматически игнорирует значения, закодированные как отсутствующие (в действительности они теперь не числовые); но это также даст мне статистику пропущенных значений только для наблюдений, которые меня интересуют (в данном случае, те, кто имеет право задавать вопрос, т. е. те, кто изначально не кодировался как '-8').
Как лучше всего справиться с этим в Пандах?
Установка:
>>> import pandas as pd
>>> df = pd.DataFrame.from_dict({
'income': [1500, -8, 10000, -2, 3000, -1, 6400]})
Желаемый результат:
>>> df.income.missing_dict = {'-1': ['.a', 'Don\'t know'], '-2': ['.b', 'Refused']} # etc.
>>> df
income
0 1500
1 Inapplic.
2 10000
3 Refused
4 3000
5 Don't know
6 6400
>>> assert df.income.mean() == np.mean([1500, 10000, 3000, 6400])
(passes)
«очевидный» обходной путь
Очевидно, что одним из вариантов является разбиение каждого столбца на два столбца: один числовой столбец с не пропущенными значениями и NaN, а другой - категориальный столбец с категориями для разных типов пропущенных значений.
Но это крайне неудобно. Эти обследования часто имеют тысячи столбцов, и исследователь вполне может использовать сотни в определенных видах экономического анализа. Наличие двух столбцов для каждого «нижележащего» столбца означает, что исследователь должен отслеживать два столбца для каждой выполняемой ею операции, например, группового режима, переименования и т. Д. Это создает бесконечные возможности для ошибок и ошибок. Это также означает, что отображение таблицы очень расточительно - для любого столбца мне нужно теперь отобразить два столбца, один из которых для любого данного наблюдения всегда избыточен. (Это расточительно как для экранной недвижимости, так и для внимания человеческих аналитиков, когда приходится определять, какие два столбца являются «парой».)
Другие идеи
Две другие мысли, которые приходят мне в голову, обе, вероятно, не идеальные:
(1) Создайте новый тип данных в пандах, который работает аналогично Stata (то есть добавляет «.a», «.b» и т. Д. К допустимым значениям для числовых столбцов).
(2) Используйте решение с двумя столбцами, приведенное выше, но (пере) пишите функции «обертки» в пандах, чтобы «groupby» и т. Д. Отслеживал пары столбцов для меня.
Я подозреваю, что (1) является лучшим решением в долгосрочной перспективе, но, по-видимому, это потребует огромного количества разработки.
С другой стороны, может быть, уже есть пакеты, которые решают эту проблему? Или у людей лучше обходные пути?