Python: установить новое значение столбца, если несколько столбцов в кадре данных имеют любое значение, кроме одной конкретной строки - PullRequest
0 голосов
/ 14 сентября 2018

Первая публикация вопроса от новичка, открытого для предложений и улучшений.

Я пытаюсь создать новый столбец в кадре данных.Новый столбец для каждой строки должен быть заполнен следующим образом:

1) «Неизвестно», если все выбранные столбцы в этой строке содержат значение «Нет».

2) НеЗначение «Нет», если один из столбцов содержит такое значение.

В наборе данных, который я использую, будет только одно значение, отличное от «Нет», если оно есть, на строку, а имя столбца будетто же самое, что и значение ячейки.

Я знаю, что мог бы пройтись по каждой строке, чтобы найти в этих столбцах значение, отличное от «Нет», и, если он был найден, установить для него значение столбца (в противном случае установить значение «Неизвестно»), но я чувствую, что упускаю что-то простое, чтобы заставить это работать.

Я смотрел на выбор значения с помощью .loc / .iloc / .at и нескольких других методов, но я нечувствую, что я уже близко.

import pandas as pd
import numpy as np

df = pd.DataFrame({'A': ['None', 'None', 'None', 'None'],
                   'B': ['None', 'B', 'None', 'None'],
                   'C': ['None', 'None', 'C', 'None'],
                   'D': ['None', 'None', 'None', 'D']})

values = ['B', 'C', 'D']

#In the code below, replace the string  'This should be non-None value (B, C or D)' with an expression
df['Letter'] = pd.np.where(df[values].eq(values).any(1, skipna=True), 
                           'This should be non-None value (B, C or D)', 'Unknown')
print(df)

   A     B     C     D     Letter
0  None  None  None  None  Unknown                                  
1  None  B     None  None  This should be non-None value (B, C or D)
2  None  None  C     None  This should be non-None value (B, C or D)
3  None  None  None  D     This should be non-None value (B, C or D)

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

попробуй:

df['new_col'] = df.apply(lambda x: [item for item in x if item!='None'][0] if len([item for item in x if item!='None'])>0 else 'Unknown',axis=1)

но не ... другое решение намного лучше, я просто предоставлю это здесь, чтобы ты увидел, как это сделать с apply.

0 голосов
/ 14 сентября 2018

Я считаю, что нужно:

df['Letter'] = df.ne('None').dot(df.columns).replace('', 'Unknown')
#if None are not strings
#df['Letter'] = df.notna().dot(df.columns).replace('', 'Unknown')
#oldier pandas versions
#df['Letter'] = df.notnull().dot(df.columns).replace('', 'Unknown')
print(df)
      A     B     C     D   Letter
0  None  None  None  None  Unknown
1  None     B  None  None        B
2  None  None     C  None        C
3  None  None  None     D        D

Объяснение :

Получить логическую маску без None значений путем сравнения с DataFrame.ne (!=) или DataFrame.notna:

print(df.ne('None'))
       A      B      C      D
0  False  False  False  False
1  False   True  False  False
2  False  False   True  False
3  False  False  False   True

Затем используйте DataFrame.dot с именами столбцов:

print(df.ne('None').dot(df.columns))
0     
1    B
2    C
3    D
dtype: object

И последнее замените пропущенные значения на Series.replace:

print(df.ne('None').dot(df.columns).replace('', 'Unknown'))
0    Unknown
1          B
2          C
3          D
dtype: object

Другое решение:

df['Letter'] = df.replace('None', np.nan).ffill(axis=1).iloc[:, -1].fillna('Unknown')
print(df)
      A     B     C     D   Letter
0  None  None  None  None  Unknown
1  None     B  None  None        B
2  None  None     C  None        C
3  None  None  None     D        D

Объяснение :

Первая replace строки None к пропущенным значениям, если необходимо:

print (df.replace('None', np.nan))
    A    B    C    D
0 NaN  NaN  NaN  NaN
1 NaN    B  NaN  NaN
2 NaN  NaN    C  NaN
3 NaN  NaN  NaN    D

Заполнить пропущенные значения вперед:

print (df.replace('None', np.nan).ffill(axis=1))
     A    B    C    D
0  NaN  NaN  NaN  NaN
1  NaN    B    B    B
2  NaN  NaN    C    C
3  NaN  NaN  NaN    D

Выбрать последний столбец по позициям поDataFrame.iloc:

print (df.replace('None', np.nan).ffill(axis=1).iloc[:, -1])
0    NaN
1      B
2      C
3      D
Name: D, dtype: object

И последнее замените пропущенные значения на Series.fillna:

print (df.replace('None', np.nan).ffill(axis=1).iloc[:, -1].fillna('Unknown'))
0    Unknown
1          B
2          C
3          D
Name: D, dtype: object
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...