Создание фиктивных столбцов из ячеек с несколькими значениями

У меня есть DF, как показано ниже:

DF =
id  Result      
1   Li_In-AR-B, Or_Ba-AR-B
1   Li_In-AR-L, Or_Ba-AR-B
3   N
4   Lo_In-AR-U
5   Li_In-AR-U
6   Or_Ba-AR-B
6   Or_Ba-AR-L
7   N

Теперь я хочу создать новые столбцы для каждого уникального значения в Result до первого «-». Каждое другое значение в новом столбце должно быть установлено на N. Разделитель "," используется для разделения обоих экземпляров в случае нескольких значений (2 или более).

DF =
id  Result        Li_In         Lo_In       Or_Ba
1   Li_In-AR-B    Li_In-AR-B    N           Or_Ba-AR-B
1   Li_In-AR-L    Li_In-AR-L    N           Or_Ba-AR-B
3   N             N             N           N
4   Lo_In-AR-U    N             Lo_In-AR-U  N
5   Li_In-AR-U    Li_In-AR-U    N           N
6   Or_Ba-AR-B    N             N           Or_Ba-AR-B
6   Or_Ba-AR-L    N             N           Or_Ba-AR-L
7   N             N             N           N

Я думал, что смогу легко сделать это, используя .get_dummies, но это возвращает только двоичное значение для каждой ячейки.

DF_dummy = DF.Result.str.get_dummies(sep='-')
DF = pd.concat([DF,DF_dummy ],axis=1)

Также это решение для более раннего сообщения не применимо для нового случая.

m = DF['Result'].str.split('-', n=1).str[0].str.get_dummies().drop('N', axis=1) == 1
df1 = pd.concat([DF['Result']] * len(m.columns), axis=1, keys=m.columns)

Любые идеи?


person Mi.    schedule 19.08.2018    source источник
comment
Была опечатка, теперь решение работает хорошо.   -  person jezrael    schedule 19.08.2018


Ответы (1)


Используйте dictionary comprehension с конструктором DataFrame для разделения на ,\s+ для разделения запятой с одним или несколькими пробелами.

import re
f = lambda x: {y.split('-', 1)[0] : y for y in re.split(',\s+', x) if y != 'N' } 
df1 = pd.DataFrame(DF['Result'].apply(f).values.tolist(), index=DF.index).fillna('N')
print (df1)
        Li_In       Lo_In       Or_Ba
0  Li_In-AR-B           N  Or_Ba-AR-B
1  Li_In-AR-L           N  Or_Ba-AR-B
2           N           N           N
3           N  Lo_In-AR-U           N
4  Li_In-AR-U           N           N
5           N           N  Or_Ba-AR-B
6           N           N  Or_Ba-AR-L
7           N           N           N

Последнее добавление к исходному DataFrame:

df = DF. join(df1) 
print (df)
   id                  Result       Li_In       Lo_In       Or_Ba
0   1  Li_In-AR-B, Or_Ba-AR-B  Li_In-AR-B           N  Or_Ba-AR-B
1   1  Li_In-AR-L, Or_Ba-AR-B  Li_In-AR-L           N  Or_Ba-AR-B
2   3                       N           N           N           N
3   4              Lo_In-AR-U           N  Lo_In-AR-U           N
4   5              Li_In-AR-U  Li_In-AR-U           N           N
5   6              Or_Ba-AR-B           N           N  Or_Ba-AR-B
6   6              Or_Ba-AR-L           N           N  Or_Ba-AR-L
7   7                       N           N           N           N
person jezrael    schedule 19.08.2018
comment
Извините, что снова вас беспокою, но что мне нужно было бы изменить, если Li_In-AR1-B, Li_In-AR2-B было значением моего столбца, и я хотел бы сохранить только первое (Li_In-AR1-B?). Прямо сейчас он принимает последний элемент, если слова перед частью -AR совпадают. - person Mi.; 20.08.2018
comment
я думаю нужно f = lambda x: {y.split('-', 1)[0] : y for y in reversed(re.split(',\s+', x)) if y != 'N' } - person jezrael; 20.08.2018
comment
Только реверс list, созданный re.split - person jezrael; 20.08.2018