Создание 2 новых столбцов путем перебора каждой строки в нескольких других столбцах с использованием понимания списка - PullRequest
0 голосов
/ 08 января 2019

У меня есть фрейм данных с именем df, который выглядит примерно так (за исключением того, что число столбцов «Дата» увеличивается до Date_8, а есть несколько сотен клиентов - я упростил его здесь).

Client_ID  Date_1        Date_2        Date_3        Date_4
C1019876   relationship  no change     no change     no change
C1018765   no change     single        no change     no change    
C1017654   single        no change     relationship  NaN        
C1016543   NaN           relationship  no change     single
C1015432   NaN           no change     single        NaN

Я хочу создать два новых столбца, first_status и last_status. first_status должно равняться первому заданному статусу взаимосвязи в 4 столбцах даты, т. Е. Первый ответ равен либо relationship или single, а last_status должно равняться последнему заданному статусу взаимосвязи в 4 столбцах даты. Получившийся df должен выглядеть следующим образом.

Client_ID  Date_1        Date_2        Date_3        Date_4        first_status  last_status
C1019876   relationship  no change     no change     no change     relationship  relationship 
C1018765   no change     single        no change     no change     single        single    
C1017654   single        no change     relationship  NaN           single        relationship   
C1016543   NaN           relationship  no change     single        relationship  single 
C1015432   NaN           no change     single        NaN           single        single

Я думаю, что эти две колонки могут быть созданы с помощью понимания списка, но я не знаю как. Для столбца first_status я предполагаю, что код будет выполнять что-то вроде следующего в каждой строке в df:

  • Найти 1-й Date столбец, в котором задано значение (отфильтровывает NaN)
  • Если значение = no change, перейти к следующему столбцу Date
  • Если значение = relationship, first_status = relationship
  • Если значение = single, first_status = single

Для столбца last_status я представляю, что код будет выполнять что-то вроде следующего в каждой строке в df:

  • Найти последний Date столбец, в котором задано значение (отфильтровывает NaN)
  • Если значение = no change, перейти к предыдущему столбцу Date
  • Если значение = relationship, last_status = relationship
  • Если значение = single, last_status = single

Ответы [ 2 ]

0 голосов
/ 08 января 2019

Полагаю, если вы действительно хотите использовать списочное понимание, вы можете, но решение от @yatu будет намного быстрее:

# unstack and find the first column index where relationship or single occurs
first = df.unstack().groupby(level=1).apply(lambda x: (np.isin(x.values, ['relationship', 'single'])).argmax())
last = df.unstack()[::-1].groupby(level=1).apply(lambda x: (np.isin(x.values, ['relationship', 'single'])).argmax())

# list comprehension to find the index and column index pair
f_list = [x for x in enumerate(first)]
l_list = [x for x in enumerate(last)]

# list comprehension with iloc
f_val = [df.iloc[f_list[i]] for i in range(len(f_list))]
l_val = [df.loc[:, ::-1].iloc[l_list[i]] for i in range(len(l_list))]

# create columns
df['first'] = f_val 
df['last'] = l_val

  Client_ID        Date_1        Date_2        Date_3     Date_4  \
0  C1019876  relationship     no change     no change  no change   
1  C1018765     no change        single     no change  no change   
2  C1017654        single     no change  relationship        NaN   
3  C1016543           NaN  relationship     no change     single   
4  C1015432           NaN     no change        single        NaN   

          first          last  
0  relationship  relationship  
1        single        single  
2        single  relationship  
3  relationship        single  
4        single        single  

timeit результаты: 8 ms ± 230 µs per loop (mean ± std. dev. of 3 runs, 1000 loops each)

0 голосов
/ 08 января 2019

Вы можете использовать replace no change с np.nan и выбрать первое и последнее действительные значения, используя bfill и ffill соответственно:

df = df.replace('no change', np.nan)
df['first_status'] = df.bfill(axis=1).Date_1
df['last_status'] = df.loc[:,:'Date_4'].ffill(axis=1).Date_4
#df = df.fillna('no_change') # if needed

 Client_ID        Date_1        Date_2        Date_3  Date_4  first_status  \
0  C1019876  relationship           NaN           NaN     NaN  relationship   
1  C1018765           NaN        single           NaN     NaN        single   
2  C1017654        single           NaN  relationship     NaN        single   
3  C1016543           NaN  relationship           NaN  single  relationship   
4  C1015432           NaN           NaN        single     NaN        single   

    last_status  
0  relationship  
1        single  
2  relationship  
3        single  
4        single  

В случае наличия Date столбцов до n, используйте df.loc[:,:'Date_n'].ffill(axis=1).Date_n для last_status

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...