Python / Pandas: если значение равно NaN или 0, заполните значение из следующего столбца в той же строке - PullRequest
4 голосов
/ 24 марта 2020

Я просмотрел несколько постов, и они применимы только к примерам с одним столбцом или только с значениями NaN или 0, но не с обоими.

Мой df выглядит следующим образом. Я хотел бы заполнить столбец 'Main' не пропущенной или ненулевой строкой, найденной в четырех столбцах справа от нее.

current df =

import pandas as pd

d = {'Main': ['','','',''], 'col2': ['Big','','',0], 'col3': [0,'Medium',0,''], 'col4': ['','','Small',''], 'col5':['',0,'','Vsmall']}
df = pd.DataFrame(data=d)

+------+------+--------+-------+--------+
| Main | Col2 | Col3   | Col4  | Col5   |
+------+------+--------+-------+--------+
|      | Big  | 0      | ...   |        |
+------+------+--------+-------+--------+
|      | ...  | Medium | ...   | 0      |
+------+------+--------+-------+--------+
|      |      | 0      | Small |        |
+------+------+--------+-------+--------+
|      | 0    | ...    | ...   | Vsmall |
+------+------+--------+-------+--------+

желаемый вывод df

+--------+------+--------+-------+--------+
| Main   | Col2 | Col3   | Col4  | Col5   |
+--------+------+--------+-------+--------+
| Big    | Big  | 0      | ...   |        |
+--------+------+--------+-------+--------+
| Medium | ...  | Medium | ...   | 0      |
+--------+------+--------+-------+--------+
| Small  |      | 0      | Small |        |
+--------+------+--------+-------+--------+
| Vsmall | 0    | ...    | ...   | Vsmall |
+--------+------+--------+-------+--------+

Заранее спасибо!

Ответы [ 2 ]

3 голосов
/ 24 марта 2020

Идея состоит в том, чтобы заменить 0 и пустые строки пропустить значения на DataFrame.mask, затем заполнить пропущенные строки и в последний раз выбрать первый столбец:

c = ['col2','col3','col4','col5']
df['Main'] = df[c].mask(df.isin(['0','',0])).bfill(axis=1).iloc[:, 0]
print (df)
     Main col1    col2   col3
0     Big  Big    None       
1  Medium    0  Medium   None
2   Small            0  Small

Если возможно, создать список из всех возможных извлеченных строк заменить все другие значения на DataFrame.where:

['col2','col3','col4','col5']
df['Main'] = df[c].where(df.isin(['Big','Medium','Small','Vsmall'])).bfill(axis=1).iloc[:,0]
print (df)
     Main col1    col2   col3
0     Big  Big    None       
1  Medium    0  Medium   None
2   Small            0  Small

Подробности :

print (df[c].mask(df.isin(['0','',0])))
#print (df[c].where(df.isin(['Big','Medium','Small','Vsmall'])))

   col1    col2   col3
0  Big    None    NaN
1  NaN  Medium   None
2  NaN     NaN  Small

print (df[c].mask(df.isin(['0','',0])).bfill(axis=1))
     col1    col2   col3
0     Big     NaN    NaN
1  Medium  Medium   None
2   Small   Small  Small
0 голосов
/ 24 марта 2020

Исходя из представленных вами образцов данных, я думаю, что вы пытаетесь добиться декодирования однократных закодированных данных (методика classi c для преобразования категориальных данных в числовые данные в машинном обучении).

Вот код для достижения декодирования:

import pandas as pd

d = {'Main': [0,0,0,0], 'col2': ['Big','','',0], 'col3': [0,'Medium',0,''], 'col4': ['','','Small',''], 'col5':['',0,'','Vsmall']}
df = pd.DataFrame(data=d)

def reduce_function(row):
    for col in ['col2','col3','col4','col5']:
        if not pd.isnull(row[col]) and row[col] != 0 and row[col] != '':
            return row[col]

df['Main']=df.apply(reduce_function, axis=1)

Примечание. Всегда учитывайте использование сокращений (т. Е. apply()) для кадров данных, а не итераций по строкам.

...