【问题标题】:Left justify string values in a pandas DataFrame在 Pandas DataFrame 中左对齐字符串值
【发布时间】:2018-06-02 11:45:54
【问题描述】:

所以我有一个包含 180000+ 值的 DataFrame,我需要 (1) 逐行替换单元格中的重复值和某些值,以及 (2) 重新排列。这是我的数据框,df:

    key   sellyr  brand  makrc  item1  item2  item3  item4  item5  item6
0   da12  2013    imp    apt    furi   apt    nan    nan    nan    nan
1   da32  2013    sa     rye    rye    app    nan    nan    nan    nan 
2   da14  2013    sa     pro    not    pro    pan    fan    nan    nan
........

nan 值表示 np.nan。并且禁止的字符串是'not'。

所以我需要做的是检查列 item1~6 将 makrc 列中包含的字符串替换为 nan。同样,我也想用nan's替换'not's。将字符串替换为np.nan后,需要重新排列item1~6,将非nan数据左对齐到最左边的空单元格,如下图,(预期输出):

    key   sellyr  brand  makrc  item1  item2  item3  item4  item5  item6
0   da12  2013    imp    apt    furi   nan    nan    nan    nan    nan
1   da32  2013    sa     rye    app    nan    nan    nan    nan    nan 
2   da14  2013    sa     pro    pan    fan    nan    nan    nan    nan
........

正如您在第一个索引中看到的那样,我已删除 item2 中的 apt 字符串并更改为 np.nan,因为相同的字符串位于 makrc 列中。在索引 1 中,我删除了黑麦并替换为 np.nan。但是这一次,我将“app”字符串从 item2 重新排列到 item1,因为 np.nan 值应该在值之后。在索引 2 中,我替换了 pro 而不是,因为我需要将 item 列中的每个“not”字符串替换为 np.nan。我也重新安排了项目。

我尝试将所有项目列组合为一个列表并替换它,但有几行只有 np.nan 项目。你们能推荐一个理想的过程来解决我的问题吗?非常感谢。

【问题讨论】:

    标签: python string pandas dataframe nan


    【解决方案1】:

    首先,提取一段以item开头的列——

    m = df.columns.str.contains('item')
    i = df.iloc[:, m]
    

    屏蔽所有符合您条件的值。使用isin -

    j = i[~i.isin(df.makrc.tolist() + ['not'])]
    

    现在。根据 NaN 对值进行排序并分配回 -

    df.loc[:, m] = j.apply(sorted, key=pd.isnull, axis=1)
    df
    
        key  sellyr brand makrc item1 item2  item3  item4  item5  item6
    0  da12    2013   imp   apt  furi   NaN    NaN    NaN    NaN    NaN
    1  da32    2013    sa   rye   app   NaN    NaN    NaN    NaN    NaN
    2  da14    2013    sa   pro   pan   fan    NaN    NaN    NaN    NaN
    

    详情

    i
    
      item1 item2 item3 item4  item5  item6
    0  furi   apt   NaN   NaN    NaN    NaN
    1   rye   app   NaN   NaN    NaN    NaN
    2   not   pro   pan   fan    NaN    NaN
    
    j
    
      item1 item2 item3 item4  item5  item6
    0  furi   NaN   NaN   NaN    NaN    NaN
    1   NaN   app   NaN   NaN    NaN    NaN
    2   NaN   NaN   pan   fan    NaN    NaN
    

    迈向更好的性能

    您可以使用适用于对象数组的 Divakar 的 justified 函数的修改版本 -

    def justify(a, invalid_val=0, axis=1, side='left'):    
        """
        Justifies a 2D array
    
        Parameters
        ----------
        A : ndarray
            Input array to be justified
        axis : int
            Axis along which justification is to be made
        side : str
            Direction of justification. It could be 'left', 'right', 'up', 'down'
            It should be 'left' or 'right' for axis=1 and 'up' or 'down' for axis=0.
    
        """
    
        if invalid_val is np.nan:
            mask = pd.notnull(a)
        else:
            mask = a!=invalid_val
        justified_mask = np.sort(mask,axis=axis)
        if (side=='up') | (side=='left'):
            justified_mask = np.flip(justified_mask,axis=axis)
        out = np.full(a.shape, invalid_val, dtype=object) 
        if axis==1:
            out[justified_mask] = a[mask]
        else:
            out.T[justified_mask.T] = a.T[mask.T]
        return out
    
    df.loc[:, m] = justify(j.values, invalid_val=np.nan, axis=1, side='left')
    df
    
        key  sellyr brand makrc item1 item2  item3  item4  item5  item6
    0  da12    2013   imp   apt  furi   NaN    NaN    NaN    NaN    NaN
    1  da32    2013    sa   rye   app   NaN    NaN    NaN    NaN    NaN
    2  da14    2013    sa   pro   pan   fan    NaN    NaN    NaN    NaN
    

    这应该(希望)比调用apply 更快。使用针对数值数据进行优化的函数的原始版本,您会特别看到速度提升。

    【讨论】:

      猜你喜欢
      • 2012-01-30
      • 2012-08-20
      • 1970-01-01
      • 2022-01-23
      • 2014-11-04
      • 1970-01-01
      • 2020-12-23
      • 1970-01-01
      • 2011-06-21
      相关资源
      最近更新 更多