#python #python-3.x #pandas #dataframe #stata
Вопрос:
fillin
Команда Stata делает набор данных прямоугольным. Как я могу сделать то же самое с Пандами?
Я пытался смоделировать fillin
команду таким образом, но это очень медленно и дорого:
from itertools import product
collapse_df = collapse_df[['cod', 'loc_id', 'fob']]
var = list(product(collapse_df['loc_id'], collapse_df['cod']))
var = list(set([i for i in var]))
var_df = collapse_df[0:0]
for idx,item in enumerate(var):
df_t = collapse_df[(collapse_df['loc_id'] == item[0]) amp; (collapse_df['cod'] == item[1])]
if (len(df_t) == 0):
df_t.loc[0, 'loc_id'] = item[0]
df_t.loc[0, 'cod'] = item[1]
var_df = pd.concat([var_df, df_t], axis=0)
collapse_df = var_df.drop_duplicates()
Редактировать:
входные данные: https://drive.google.com/file/d/1giWlKXNFaXeLpaVSUDc04AwyogD-ASJK/view?usp=sharing
вывод: https://drive.google.com/file/d/1UcADbQnbDELGPHZVIt2BmCYYTzU5pZtf/view?usp=sharing
Комментарии:
1.
collapse_df
в настоящее время не определено. Можете ли вы предоставить некоторые примеры импорта и вывода?2. пожалуйста, предоставьте воспроизводимый кадр данных с ожидаемым результатом
3. pyjanitor имеет комплект , который похож на наполнитель. Если вы не хотите добавлять дополнительную зависимость, вы всегда можете проверить исходный код и повторить, как они подходят к проблеме ( github.com/pyjanitor-devs/pyjanitor/blob/… )
4. да, в зависимости от вашего варианта использования, вы можете использовать asfreq, повторную выборку, переиндексацию,
complete
просто абстрагируя процесс … Кроме того, ваш пример ввода-вывода недостаточно полезен/полезен/ понятен для работы5. Можете ли вы вместо этого просто заполнить первые 5 строк? Завершите ввод образца
106 17 1.350000e 04
и покажите вывод только для этих 5 строк?
Ответ №1:
Я не уверен на 100%, каков ваш желаемый результат, исходя из предоставленных вами данных. Тем не менее, я попытался решить эту проблему, исходя из того, что говорится в документах Stata.
Настройка тестовых данных (очень важно при задании вопроса, пожалуйста, предоставляйте их в будущем)
import pandas as pd
import numpy as np
import itertools
np.random.seed(42)
test_data = pd.DataFrame(
{
'AgeGroup': np.random.choice(['20-24', '18-19', '10-17'], size=10, p=[0.75, 0.20, 0.05]),
'Sex': np.random.choice(['male', 'female'], size=10),
'Race': np.random.choice(['black', 'white'], size=10, p=[0.3, 0.7]),
'x1': np.random.uniform(size=10),
'x2': np.random.normal(0, 1, size=10)
}
)
test_data
Из:
AgeGroup Sex Race x1 x2
0 20-24 female black 0.785176 -0.600254
1 10-17 male white 0.199674 0.947440
2 20-24 female white 0.514234 0.291034
3 20-24 female white 0.592415 -0.635560
4 20-24 female black 0.046450 -1.021552
5 20-24 female white 0.607545 -0.161755
6 20-24 female black 0.170524 -0.533649
7 18-19 female black 0.065052 -0.005528
8 20-24 female white 0.948886 -0.229450
9 20-24 female white 0.965632 0.389349
Мой подход в основном:
- Найдите все возможные комбинации столбцов идентификаторов
- Найдите, какие комбинации не существуют в предоставленном наборе данных
- Создайте пустой набор данных с отсутствующими комбинациями и объедините его с существующим набором данных
def fill_in(df, id_cols):
"""Fill in empty records for combinations of id_cols that do not exist
in dataset.
Args:
df: dataset
id_cols: list of identity columns
Returns:
filled_df: dataframe with empty records for missing combinations of id_cols
"""
# create all possible unique combinations of id_cols
# and find combos that do not exist in the dataset
id_combos = list(itertools.product(*[df[c].unique() for c in id_cols]))
existing_combos = df[id_cols].apply(tuple, axis=1).unique()
missing_combos = set(id_combos) - set(existing_combos)
# create an empty dataframe with the missing combos
other_cols = [c for c in df.columns if c not in id_cols]
new_idx = pd.MultiIndex.from_tuples(missing_combos, names=id_cols)
empty_data = np.empty(shape=(len(missing_combos), len(other_cols))).fill(np.nan)
filled_df = pd.DataFrame(data=empty_data, index=new_idx, columns=other_cols).reset_index()
# concat dataset with empty dataset for missing combos
return pd.concat([df.assign(_fill_in=0), filled_df.assign(_fill_in=1)])
Опробовать это:
fill_df(test_data, ['AgeGroup', 'Sex', 'Race'])
Результаты:
AgeGroup Sex Race x1 x2 _fill_in
0 20-24 female black 0.785176 -0.600254 0
1 10-17 male white 0.199674 0.947440 0
2 20-24 female white 0.514234 0.291034 0
3 20-24 female white 0.592415 -0.635560 0
4 20-24 female black 0.046450 -1.021552 0
5 20-24 female white 0.607545 -0.161755 0
6 20-24 female black 0.170524 -0.533649 0
7 18-19 female black 0.065052 -0.005528 0
8 20-24 female white 0.948886 -0.229450 0
9 20-24 female white 0.965632 0.389349 0
0 10-17 female white NaN NaN 1
1 10-17 female black NaN NaN 1
2 18-19 male black NaN NaN 1
3 10-17 male black NaN NaN 1
4 18-19 male white NaN NaN 1
5 18-19 female white NaN NaN 1
6 20-24 male white NaN NaN 1
7 20-24 male black NaN NaN 1