Как заполнить NA с минимальным значением строк для выбранного столбца на пользователя с пандами - PullRequest
2 голосов
/ 16 мая 2019
    sample = {'user_id': ['u_id1', 'u_id2', 'u_id3','u_ud4'],
    'len_1': [150, 'NA', 50, 50],
     'len_2': [150, 200, 50, 60],
     'len_3': [200, 210, 90, 50],
      'len_4': [200, 205, 90, 40],

     'speed_1': [140, 'NA', 'NA','NA'],
     'speed_2': [140, 215, 90, 'NA'],
     'speed_3': ['NA', 210, 95, 50],
      'speed_4': ['NA', 215, 95, 30],

     'value_1': ['NA', 215, 'NA', 'NA'],
     'value_2': [130, 'NA', 95, 50],
      'value_3': [120, 'NA', 'NA', 40],
     'value_4': ['NA', 'NA', 90, 10]}
    df = pd.DataFrame.from_dict(sample)
    df.set_index('user_id')
    df

У меня есть приведенный выше пример фрейма данных.Он имеет значения «NA» для некоторых столбцов.enter image description here Я хочу заполнить значения 'NA'.Пример: -

«u_id1» имеет «NA» при «speed_3» и «speed_4», поэтому «speed_3 =» speed_4 = min {speed_1, speed_2,speed_3, speed_4} => 140

«u_id2» имеет «NA 'at' len_1 ', поэтому' len_1 = min {len_1, len_2, len_3, len_4} => 200.

Если возможно, я хочу проверить процент значений 'NA'.т.е. за {len_1, len_2, len_3, len_4}, за {speed_1, speed_2,speed_3, speed_4} и т. д. для каждого пользователя.Так что я могу решить, заполнять ли минимальным значением или нет.например, если 75% из {value_1, value_2, value_3, value_4} равны 'NA', то не заполняйте значениями NA (потому что буква, которую я хочу отфильтровать).

Ожидаемый результат должен выглядеть примерно так

   sample = {'user_id': ['u_id1', 'u_id2', 'u_id3','u_ud4'],
    'len_1': [150, 200, 50, 50],
     'len_2': [150, 200, 50, 50],
     'len_3': [200, 210, 90, 50],
      'len_4': [200, 205, 90, 50],

     'speed_1': [140, 215, 95, 30],
     'speed_2': [140, 215, 95, 30],
     'speed_3': [140, 215, 95, 50],
      'speed_4': [140, 215, 95, 30],

     'value_1': [120, 215, 90, 10],
     'value_2': [130, 'NA', 95, 50],
      'value_3': [120, 'NA', 90, 40],
     'value_4': [120, 'NA', 90, 10]}
df_out = pd.DataFrame.from_dict(sample)

enter image description here Примечание: для пользователя 'u_id2' { value_2,value_3, value_4} остаются NA, поскольку 75% из них были значениями 'NA'

Я ценю любую помощь покак подойти к этому.

Ответы [ 2 ]

2 голосов
/ 16 мая 2019

Если необходимо заменить пропущенные значения для групп именами столбцов, разделенными на _, используйте:

sample = {'user_id': ['u_id1', 'u_id2', 'u_id3','u_ud4'],
            'len_1': [150, 'NA', 50, 50],
             'len_2': [150, 200, 50, 50],
             'len_3': [200, 210, 90, 50],
             'len_4': [200, 210, 90, 50],    
             'speed_1': [140, 'NA', 'NA','NA'],
             'speed_2': [140, 215, 95, 'NA'],
             'speed_3': ['NA', 215, 95, 50],
             'speed_4': ['NA', 215, 95, 50],
             'value_1': ['NA', 215, 'NA', 'NA'],
             'value_2': [140, 'NA', 95, 50],
             'value_3': ['NA', 'NA', 'NA', 50],
             'value_4': ['NA', 'NA', 'NA', 50]}
df = pd.DataFrame.from_dict(sample)

#convert to index and convert NA to np.nan
df = df.set_index('user_id')
df = df.apply(pd.to_numeric, errors='coerce')

print (df)
         len_1  len_2  len_3  len_4  speed_1  speed_2  speed_3  speed_4  \
user_id                                                                   
u_id1    150.0    150    200    200    140.0    140.0      NaN      NaN   
u_id2      NaN    200    210    210      NaN    215.0    215.0    215.0   
u_id3     50.0     50     90     90      NaN     95.0     95.0     95.0   
u_ud4     50.0     50     50     50      NaN      NaN     50.0     50.0   

         value_1  value_2  value_3  value_4  
user_id                                      
u_id1        NaN    140.0      NaN      NaN  
u_id2      215.0      NaN      NaN      NaN  
u_id3        NaN     95.0      NaN      NaN  
u_ud4        NaN     50.0     50.0     50.0  

Вы можете использовать DataFrame.isna для проверки отсутствиязначения, затем DataFrame.groupby с первыми значениями имен разделенных столбцов и получить mean с GroupBy.transform для возврата DataFrame, заполненной одинаковыми значениями по группам, сравнить по порогу:

mask = df.isna().groupby(lambda x: x.split('_')[0], axis=1).transform('mean') < .75
print (mask)
         len_1  len_2  len_3  len_4  speed_1  speed_2  speed_3  speed_4  \
user_id                                                                   
u_id1     True   True   True   True     True     True     True     True   
u_id2     True   True   True   True     True     True     True     True   
u_id3     True   True   True   True     True     True     True     True   
u_ud4     True   True   True   True     True     True     True     True   

         value_1  value_2  value_3  value_4  
user_id                                      
u_id1      False    False    False    False  
u_id2      False    False    False    False  
u_id3      False    False    False    False  
u_ud4       True     True     True     True  

Затем замените на DataFrame.fillna только значения, отфильтрованные по маске:

df[mask] = df.fillna(df.groupby(lambda x: x.split('_')[0], axis=1).transform('min'))
print (df)
         len_1  len_2  len_3  len_4  speed_1  speed_2  speed_3  speed_4  \
user_id                                                                   
u_id1    150.0    150    200    200    140.0    140.0    140.0    140.0   
u_id2    200.0    200    210    210    215.0    215.0    215.0    215.0   
u_id3     50.0     50     90     90     95.0     95.0     95.0     95.0   
u_ud4     50.0     50     50     50     50.0     50.0     50.0     50.0   

         value_1  value_2  value_3  value_4  
user_id                                      
u_id1        NaN    140.0      NaN      NaN  
u_id2      215.0      NaN      NaN      NaN  
u_id3        NaN     95.0      NaN      NaN  
u_ud4       50.0     50.0     50.0     50.0  
0 голосов
/ 16 мая 2019

Вы можете сделать что-нибудь подобное:

def f(arr):
    s1,s2,s3,s4 = arr
    if pd.isnull(s1):
        s1 = min(s2,s3,s4)
    # your code ...
    return s1,s2,s3,s4

df = df.apply(d, axis=1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...