【问题标题】:Python Pandas set value for specific rows matching conditionPython Pandas为特定行匹配条件设置值
【发布时间】:2020-07-10 10:39:25
【问题描述】:

根据数据框列 del 值,查看其他列 col_0-14,然后将该行的值设置为 100(不更新 nan 值)。

数据框看起来像:

id  val_1   del col_1   col_2   col_3   col_4   col_5   col_6   col_7   col_8   col_9   col_10  col_11  col_12  col_13  col14
1   13      0   0   0   0   0   0   0   0   0   0   0   0   0   
2   11      0   0   0   0   0   0   0   0   0   0   0           
3   8   1   0   0   0   0   0   7   7   8                       
4   6   1   500 1000    1500    2000    2500    3000

作为第 3、4 行的 del,代码应将值替换为 100 直到 val_1 值。

3   8   1   100 100 100 100 100 100 100 100 
4   6   1   100 100 100 100 100 100

我试过了:

df.loc[df['del'] == 1, df.columns.str.startswith('col')] = 100

它将所有行值 (col1-14) 替换为 100。有没有办法,我可以控制它直到 val_1 值,而 col 的其余部分保持为 nan 值。 或

在上面的代码之后,我可以使用 val_1 值通过循环逻辑使用 nan 值再次更新行。

def cut_data(row):
    for i in range(1, 15):
        if i > row['val_1']:
            row['col_' + str(i)] = np.NaN
            
    return row

df = df.apply(cut_data, axis=1)

请建议任何替代循环逻辑的方法,即没有循环。

DDL 生成 DataFrame:

df1 = pd.DataFrame({'id': [1, 2, 3, 4],
                   'val_1': [13, 11, 8, 6],
                   'del' : [np.nan,np.nan,1,1], 
                   'col1': [0, 0, 0, 500],
                   'col2': [0, 0, 0, 1000],
                   'col3': [0, 0, 0, 1500],
                   'col4': [0, 0, 0, 2000],
                   'col5' : [0, 0, 0, 2500],
                   'col6': [0, 0, 7, 3000],
                   'col7': [0, 0, 7,np.nan ],
                   'col8': [0, 0, 7, np.nan],
                   'col9': [0, 0, np.nan, np.nan],
                   'col10': [0, 0, np.nan, np.nan],
                   'col11': [0, 0, np.nan, np.nan],
                   'col12': [0, np.nan, np.nan, np.nan],
                   'col13': [0, np.nan, np.nan, np.nan],
                   'col14': [ np.nan, np.nan, np.nan, np.nan]})

谢谢!

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    上次编辑的解决方案:

    #extract columns names starting by col
    c = df.columns[df.columns.str.startswith('col')]
    
    #created 2d mask by compare 1d arrange array by length of c for 2d mask
    colsarray = np.arange(len(c))
    max1 = df['val_1'].to_numpy()[:, None]
    
    print (max1)
    [[13]
     [11]
     [ 8]
     [ 6]]
    
    mask1 = colsarray < max1
    
    print (mask1)
    [[ True  True  True  True  True  True  True  True  True  True  True  True
       True False]
     [ True  True  True  True  True  True  True  True  True  True  True False
      False False]
     [ True  True  True  True  True  True  True  True False False False False
      False False]
     [ True  True  True  True  True  True False False False False False False
      False False]]
    

    mask2 = df['del'] == 1
    print (mask2)
    0    False
    1    False
    2     True
    3     True
    Name: del, dtype: bool
    
    #chain by mask2 by & for bitwise AND - first 2 rows are set to False
    mask = mask1 & mask2.to_numpy()[:, None]
    print (mask)
    [[False False False False False False False False False False False False
      False False]
     [False False False False False False False False False False False False
      False False]
     [ True  True  True  True  True  True  True  True False False False False
      False False]
     [ True  True  True  True  True  True False False False False False False
      False False]]
    
    #repalce only filtered rows by columns c
    df[c] = np.where(mask, 100, df[c])
    

    print (df)
       id  val_1  del   col1   col2   col3   col4   col5   col6   col7   col8  \
    0   1     13  NaN    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0   
    1   2     11  NaN    0.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0   
    2   3      8  1.0  100.0  100.0  100.0  100.0  100.0  100.0  100.0  100.0   
    3   4      6  1.0  100.0  100.0  100.0  100.0  100.0  100.0    NaN    NaN   
    
       col9  col10  col11  col12  col13  col14  
    0   0.0    0.0    0.0    0.0    0.0    NaN  
    1   0.0    0.0    0.0    NaN    NaN    NaN  
    2   NaN    NaN    NaN    NaN    NaN    NaN  
    3   NaN    NaN    NaN    NaN    NaN    NaN  
    

    【讨论】:

    • 谢谢耶兹瑞尔!当 del == 1 存在于 1 行时,它起作用。如果 del == 1 存在于多行中怎么办?您还可以建议上述循环的任何替代方法吗?
    • @Anku - 如果del 列中有多个1 值,则经过测试并且工作良好。
    • 道歉@jezrael,你的答案是正确的!但我错过了指出值 6 是基于列 val_1 值。对于每一行,它都有不同的值,如果我在行上有多个 del,比如你的例子,row1 和 row3,col1-14 值应该更新到 val_1 值。 (同时我也在编辑我的问题)。
    • @Anku - 我添加了 numpy 解决方案,像循环一样复杂,但非常快,因为矢量化了。
    猜你喜欢
    • 2018-01-20
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 1970-01-01
    • 2018-01-14
    • 1970-01-01
    相关资源
    最近更新 更多