приведите фрейм данных к длинным, удаляющим строкам, расширяющим другие

#python #pandas #melt

Вопрос:

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

 import pandas as pd import io  _1 = pd.read_csv(io.StringIO(  """date; origin; val_one; val_two; aaa; bbb; ccc; ddd; eee; fff  10/11/2009; aaa; 1; 0; 0; 0; 0; 0; 1; 0  10/11/2009; bbb; 0; 1; 1; 0; 0; 0; 0; 1  10/11/2009; ccc; 0; 1; 0; 0; 0; 0; 0; 0  10/11/2009; ddd; 0; 2; 0; 1; 1; 1; 0; 0"""),  sep=";").set_axis(['date', 'origin', 'val_one', 'val_two',  'aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'], axis=1)  

Теперь я хочу создать исходно-целевые (строки aaa : fff ) диады. Строки , в которых нет цели (т. е. ни один из целевых столбцов не является 1 , например, третьей строкой, индекс 2), должны быть удалены; строки, в которых существует более одной цели (например, вторая строка, индекс 1, где aaa находится 1 и fff является одним из целевых столбцов 1 ), должны быть превращены в две строки. Ожидаемый результат составляет:

 _2_targ = pd.read_csv(io.StringIO( """date; origin; val_one; val_two; target 10/11/2009; aaa; 1; 0; eee 10/11/2009; bbb; 0; 1; aaa 10/11/2009; bbb; 0; 1; fff 10/11/2009; ddd; 0; 2; bbb 10/11/2009; ddd; 0; 2; ccc 10/11/2009; ddd; 0; 2; ddd"""),  sep=';').set_axis(['date', 'origin', 'val_one', 'val_two', 'target'])  

Я пытался использовать pd.melt безрезультатно (см. Ниже) — это создает все диады, даже те, которые я не хочу сохранять (потому что целевого столбца нет 1 ).

 _2 = pd.melt(_1,  id_vars=['date', 'origin', 'val_one', 'val_two'],  value_vars=['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'],  var_name='target', value_name='tmp')  

Что я упускаю?

Комментарии:

1. output = _2[_2["tmp"].gt(0]].drop("tmp",1)

Ответ №1:

Я верю, что вы можете расплавиться точно так же, как вы это делаете, а затем удалить строки из вашего long_df, которые имеют значение 0 для tmp

 import pandas as pd import io  #nice reproducible input! df1 = pd.read_csv(io.StringIO(  """date; origin; val_one; val_two; aaa; bbb; ccc; ddd; eee; fff  10/11/2009; aaa; 1; 0; 0; 0; 0; 0; 1; 0  10/11/2009; bbb; 0; 1; 1; 0; 0; 0; 0; 1  10/11/2009; ccc; 0; 1; 0; 0; 0; 0; 0; 0  10/11/2009; ddd; 0; 2; 0; 1; 1; 1; 0; 0"""),  sep=";").set_axis(['date', 'origin', 'val_one', 'val_two',  'aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'], axis=1)  #Melt exactly the same as you did long_df = pd.melt(  df1,  id_vars=['date', 'origin', 'val_one', 'val_two'],  value_vars=['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'],  var_name='target', value_name='tmp' )  #Filter out rows where tmp is 0, sort to match your output, and drop the tmp column long_df = long_df[long_df['tmp'].gt(0)].sort_values('origin').drop(columns='tmp').reset_index(drop=True) long_df  

Результат почти такой, как вы показываете выше, но я думаю, что вы забыли bbb:fff строку

 date origin val_one val_two target 0 10/11/2009 aaa 1 0 eee 1 10/11/2009 bbb 0 1 aaa 2 10/11/2009 bbb 0 1 fff 3 10/11/2009 ddd 0 2 bbb 4 10/11/2009 ddd 0 2 ccc 5 10/11/2009 ddd 0 2 ddd  

Я также переименовал ваши переменные, но это, очевидно, не важно

Комментарии:

1. Спасибо. Также вы были правы насчет вывода: вывод, данный вашим ответом, верен, я обновил ошибку в вопросе.