如何使用 pandas 为每个用户所选列的行的最小值填充 NA

问题描述 投票:0回答:2
    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”值。 我想填写“NA”值。 示例:-

'u_id1' 在 'speed_3' 和 'speed_4' 处具有“NA”,因此 'speed_3 = 'speed_4 = min

{speed_1, speed_2,speed_3, speed_4}
=> 140

'u_id2' 在 'len_1' 处具有“NA”,因此 '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}
等。这样我就可以决定是否用最小值填充。例如,如果 {value_1, value_2,value_3, value_4} 的 75% 是“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)

注意:对于用户 'u_id2'

{ value_2,value_3, value_4}
保持 NA,因为其中 75% 是 'NA' 值

我感谢任何有关如何解决此问题的帮助。

python pandas numpy
2个回答
2
投票

如果需要用按

_
分割的列名称替换每组的缺失值,请使用:

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
投票
def function1(dd: pd.DataFrame):
    return dd.apply(lambda ss: ss if (1-ss.dropna().pipe(len)/(ss.size))>=0.75 else ss.fillna(ss.min()))

dd1=pd.wide_to_long(df, stubnames=['len', 'speed', 'value'], i='user_id', j='col1',sep='_').replace("NA",pd.NA)
dd1.groupby(level=0, as_index=0, group_keys=0).apply(function1).stack().reset_index().assign(col1=lambda dd:dd.level_2+'_'+dd.col1.astype(str)).drop("level_2",1).pivot(index="user_id",columns="col1",values=0).rename_axis(None,axis=1)


         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  
© www.soinside.com 2019 - 2024. All rights reserved.