Pandas: наложение столбца на строку с пустым

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

У меня есть фрейм данных, который выглядит следующим образом:

                 dcc3   manager1   manager2
party_num                                 
L21635789  SBAS01030  A22677981        NaN
L21635789  SBAS02030        NaN  A22810282
L21635789  SBAS03030        NaN  A21721880
  

Я пытаюсь «наложить» одну строку (неважно, какую) из присутствующего manager2 в строку, в которой manager1 является пустым / NaN, вот так:

                 dcc3   manager1   manager2
party_num                                 
L21635789  SBAS01030  A22677981  A22810282
L21635789  SBAS02030        NaN        NaN
L21635789  SBAS03030        NaN        NaN
  

или

                 dcc3   manager1   manager2
party_num                                 
L21635789  SBAS01030  A22677981  A21721880
L21635789  SBAS02030        NaN        NaN
L21635789  SBAS03030        NaN        NaN
  

очевидно, нам нужно переиндексировать DCC3, но что потом? Необходимо наложить только эти 2 столбца (и только эти столбцы, поскольку другие существуют)

Я действительно мог бы воспользоваться помощью, заранее благодарю вас.

РЕДАКТИРОВАТЬ 1:

Извините, я не уточнил, это элементарный случай. Возможно, есть случаи, когда это всего лишь одно значение (где это не применимо) или до 5-6. В качестве примера я использовал 3 строки.

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

1. вы пробовали manager1.ffill()

2. Можете ли вы объяснить, каков ваш конечный желаемый результат? Вы хотите, чтобы вторые две строки были NaN для manager1 и manager2?

3. @JoeFerndz, нет, у меня нет. Я проверю это

4. @B.Bogart, конечный результат — один из 2 нижних результатов. Обратите внимание, как в первой строке есть один из того же индекса под ним.

Ответ №1:

Эти две строки кода должны решить проблему для вас.

 df.manager2 = df.manager2.bfill().ffill()
df.loc[df.manager1.isnull(), 'manager2'] = np.NaN
  

Ниже приведены несколько сценариев, которые я пробовал, и код тот же. Посмотрите, хотите ли вы этого.

 import pandas as pd
import numpy as np
c=['party_num','dcc3','manager1','manager2']
  

Сценарий 1:

строка 1: manager1 = NaN, manager2 = значение

Результаты: присвоить значение manager2 строке 2

 print ('nScenario 1')
print ('row 1: manager 1: NaN, manager 2: value; pick row2 manager 1 value')
d  = [['L21635789','SBAS01030',np.NaN,'A22810282'],
     ['L21635789','SBAS02030','A22677981',np.NaN],
     ['L21635789','SBAS03030',np.NaN,'A21721880']]

df = pd.DataFrame(data=d,columns=c)
print (df)
df.manager2 = df.manager2.bfill().ffill()
df.loc[df.manager1.isnull(), 'manager2'] = np.NaN
print ()
print (df)
  

Вывод для сценария 1:

 Scenario 1
row 1: manager 1: NaN, manager 2: value; pick row2 manager 1 value
   party_num       dcc3   manager1   manager2
0  L21635789  SBAS01030        NaN  A22810282
1  L21635789  SBAS02030  A22677981        NaN
2  L21635789  SBAS03030        NaN  A21721880

   party_num       dcc3   manager1   manager2
0  L21635789  SBAS01030        NaN        NaN
1  L21635789  SBAS02030  A22677981  A21721880
2  L21635789  SBAS03030        NaN        NaN
  

Сценарий 2:

строка 1: manager1 = значение, manager2 = NaN

Результаты: присвоить значение manager2 строке 1

 print ('nScenario 2')
print ('row 1: manager 1: value, manager 2: NaN; pick row2 manager 2 value')

d = [['L21635789','SBAS01030','A22677981',np.NaN],
     ['L21635789','SBAS02030',np.NaN,'A22810282'],
     ['L21635789','SBAS03030',np.NaN,'A21721880']]

df = pd.DataFrame(data=d,columns=c)
print (df)
df.manager2 = df.manager2.bfill().ffill()
df.loc[df.manager1.isnull(), 'manager2'] = np.NaN
print ()
print (df)
  

Вывод для сценария 2:

 Scenario 2
row 1: manager 1: value, manager 2: NaN; pick row2 manager 2 value
   party_num       dcc3   manager1   manager2
0  L21635789  SBAS01030  A22677981        NaN
1  L21635789  SBAS02030        NaN  A22810282
2  L21635789  SBAS03030        NaN  A21721880

   party_num       dcc3   manager1   manager2
0  L21635789  SBAS01030  A22677981  A22810282
1  L21635789  SBAS02030        NaN        NaN
2  L21635789  SBAS03030        NaN        NaN
  

Сценарий 3:

строка 1: manager1 = NaN, manager2 = NaN

строка 2: manager1 = значение; manager2 = NaN; строка 3: manager2 = значение

Результаты: присвоить значение manager3 строке 2

 print ('nScenario 3')
print ('row 1: manager 1: NaN, manager 2: NaN; pick row2 manager 1 amp; row 3 manager 2')

d = [['L21635789','SBAS01030',np.NaN,np.NaN],
     ['L21635789','SBAS02030','A22677981',np.NaN],
     ['L21635789','SBAS03030',np.NaN,'A21721880']]

df = pd.DataFrame(data=d,columns=c)
print (df)
df.manager2 = df.manager2.bfill().ffill()
df.loc[df.manager1.isnull(), 'manager2'] = np.NaN
print ()
print (df)
  

Вывод для сценария 3:

 Scenario 3
row 1: manager 1: NaN, manager 2: NaN; pick row2 manager 1 amp; row 3 manager 2
   party_num       dcc3   manager1   manager2
0  L21635789  SBAS01030        NaN        NaN
1  L21635789  SBAS02030  A22677981        NaN
2  L21635789  SBAS03030        NaN  A21721880

   party_num       dcc3   manager1   manager2
0  L21635789  SBAS01030        NaN        NaN
1  L21635789  SBAS02030  A22677981  A21721880
2  L21635789  SBAS03030        NaN        NaN
  

Сценарий 4:

строка 1: manager1 = значение, manager2 = NaN

строка 3: manager1 = значение, manager2 = значение

Результаты: игнорируйте строки 1 и 2, поскольку в строке 3 есть значения как для manager1, так и для manager2

 print ('nScenario 4')
print ('row 1: manager 1: NaN, manager 2: value; row3 has both manager 1 amp; manager 2')

d = [['L21635789','SBAS01030',np.NaN,'A21721880'],
     ['L21635789','SBAS02030',np.NaN,np.NaN],
     ['L21635789','SBAS03030','A22677981','A21721882']]

df = pd.DataFrame(data=d,columns=c)
print (df)
df.manager2 = df.manager2.bfill().ffill()
df.loc[df.manager1.isnull(), 'manager2'] = np.NaN
print ()
print (df)
  

Вывод для сценария 4:

 Scenario 4
row 1: manager 1: NaN, manager 2: value; row3 has both manager 1 amp; manager 2
   party_num       dcc3   manager1   manager2
0  L21635789  SBAS01030        NaN  A21721880
1  L21635789  SBAS02030        NaN        NaN
2  L21635789  SBAS03030  A22677981  A21721882

   party_num       dcc3   manager1   manager2
0  L21635789  SBAS01030        NaN        NaN
1  L21635789  SBAS02030        NaN        NaN
2  L21635789  SBAS03030  A22677981  A21721882
  

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

1. Очень тщательно. Тестирую его сейчас.

2. Я думаю, это сработает, но для этого может потребоваться groupby??? все еще смотрю на это.

Ответ №2:

Вы могли бы использовать np.where для достижения этой цели:

 df['manager2'] = np.where(df['manager1'].notnull() amp; df['manager2'].isnull(),
                          df['manager2'].dropna().iloc[0], np.nan) # You could do df['manager2'].dropna().iloc[1] for the other value
df
Out[1]: 
                dcc3   manager1   manager2
party_num                                 
L21635789  SBAS01030  A22677981  A22810282
L21635789  SBAS02030        NaN        nan
L21635789  SBAS03030        NaN        nan
  

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

1. Я попробовал ваш код для сценария 2 в моем варианте и обнаружил некоторые проблемы. Можете ли вы разобраться в этом и сообщить мне, что я делаю неправильно, пожалуйста?

2. @JoeFerndz хорошее место, мы должны использовать .iloc[0] вместо [0]

3. ДА. теперь это работает для всех условий, кроме сценария 4. Поскольку вы специально смотрите на iloc[0], сценарий 4 завершается с ошибкой.

4. @JoeFerndz это не сбой из-за iloc . Сбой происходит из-за np.where условия, которое: df['manager1'].notnull() amp; df['manager2'].isnull() Я не уверен, требуются ли оба этих условия, но если нет, то op просто удалит одно из двух условий ИЛИ изменит amp; знак на | знак.

5. Очень близко. Я действительно впечатлен. Я правильно ввожу первую запись, но все, что приведено ниже, является только первым значением (для столбца manager 2, т.е. Первого значения manager 2).