Панды — перебирайте строки в определенном столбце и находите пустые ячейки

#python #pandas #dataframe

Вопрос:

У меня есть фрейм данных с более чем 50 000 строками.

вход : введите описание изображения здесь

Я пытаюсь перебирать строки до первой пустой ячейки, а затем копировать значение идентификатора только в том случае, если par существует. К сожалению, это не работает.

Другими словами, то, что я хочу сделать, — это заменить par значением столбца 1 (id_1, id_2, id_3) на столбец 3 соответственно. Результат будет примерно таким :

введите описание изображения здесь

Любая идея или помощь будут оценены по достоинству. Заранее всем вам спасибо !

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

1. np.where(df['Column3'] == 'par', df['Column1'], np.nan) ?

2. @It_is_Chris это не поможет, np.где нельзя использовать таким образом. Посмотрите на значения в столбце 1.

Ответ №1:

Вы можете использовать .where() и ffill() для заполнения каждой группы одинаковыми id id значениями в каждой строке Column1 . Затем измените Column3 значения с par на эти id значения в той же строке , используя .mask() , как показано ниже:

 Col1_id = df['Column1'].where(df['Column1'].str.startswith('id_')).ffill()

df['Column3'] = df['Column3'].mask(df['Column3'] == 'par', Col1_id)
 

Результат:

 print(df)

   Column1 Column2 Column3
0     id_1     NaN     NaN
1    n="1"   whose    id_1
2    n="2"  theirs    id_1
3    n="3"      am    id_1
4      NaN     NaN     NaN
5     id_2     NaN     NaN
6    n="4"      in    id_2
7    n="5"     out    id_2
8      NaN     NaN     NaN
9     id_3     NaN     NaN
10   n="6"      in    id_3
11   n="7"     out    id_3
 

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

1. @Artemis Возможно ли, что в столбце 3 будут значения, отличные от par и NaN ? Если да, то будьте осторожны, что решение Аркадиуша может повысить их ценность NaN , в то время как мое решение должно хорошо работать с этим.

2. Я добавил комментарий к своему ответу с объяснением того, что можно сделать в такой ситуации. Из сообщения с вопросом мы можем заключить, что в колонке 3 есть » par » и «nan». Если есть что — то большее-тогда это решение пользователя. Он может решить, лучше ли поместить туда » нан » или оставить существующее значение.

3. @SeaBean большое вам спасибо за разъяснение. К счастью, он содержит только par и NaN, но спасибо за объяснение, я бы этого не сделал.

Ответ №2:

  1. Разделите фрейм данных на пустые строки с помощью numpy.split .
  2. Если «par» находится в столбце 3, замените все «par» в столбце 3 первым ненулевым значением из «Столбца 1», используя str.replace
  3. Добавьте измененный «фрагмент» к выходным данным.

Решение:

 import numpy as np

output = pd.DataFrame()
for chunk in np.split(df, df[df.isnull().all(1)].index):
    if "par" in chunk["Column3"].tolist():
        chunk["Column3"] = chunk["Column3"].str.replace("par", chunk["Column1"].dropna().iat[0])
    output = output.append(chunk)

>>> output
   Column1 Column2 Column3
0     id_1    None    None
1    n="1"   whose    id_1
2    n="2"  theirs    id_1
3    n="3"      am    id_1
4     None    None    None
5     id_2    None    None
6    n="4"      in    id_2
7    n="5"     out    id_2
8     None    None    None
9     id_3    None    None
10   n="6"      in    id_3
11   n="7"     out    id_3
 

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

1. Спасибо вам за подробный ответ. По соображениям простоты я не использовал точный формат моего df (огромная ошибка, приношу свои извинения). df начинается с 3 дополнительных строк и не заканчивается на par. 1-я строка: все столбцы пусты 2-я : столбец 1 : <название>, столбец 2 и столбец 3: пусто 3-я: все столбцы пусты и заканчиваются столбцом 1: <название></название></название></конец>, столбец 2 и столбец 3: пусто

2. Форматирование полностью теряется в комментариях, поэтому я не понимаю, что вы имеете в виду. Не могли бы вы обновить свой вопрос, чтобы объяснить, в чем проблема?

3. Я проверил ваш код так, как если бы фрейм данных начинался непосредственно со строки id_1, а столбец 3 заканчивался на par, и это работает. Это была моя вина, что я с самого начала не предоставил правильный формат. Еще раз спасибо вам!

Ответ №3:

Ты мог бы поступить так же:

 import numpy as np

df['Column3'] = np.where(df['Column3'].eq('par'),
                         df['Column1'].where(df['Column1'].str.contains('id')).ffill(),
                         np.nan)
 

Выход:

     Column1  Column2  Column3
0      id_1      NaN      NaN
1     n="1"    whose     id_1
2     n="2"   theirs     id_1
3     n="3"       am     id_1
4      id_2      NaN      NaN
5     n="4"       in     id_2
6     n="5"      out     id_2
7      id_3      NaN      NaN
8     n="6"       in     id_3
9     n="7"      out     id_3
 

Редактировать:

Если в столбце 3 также есть другие значения, кроме «par», вы можете поместить df [«Столбец 3″] вместо np.nan в конце функции. Это ваше решение, хотите ли вы поместить » nan «в этот столбец для значений, отличных от «par», или оставить значения, которые там уже существуют.