【问题标题】:Assign NaN to a column based on another column将 NaN 分配给基于另一列的列
【发布时间】:2020-05-29 17:18:53
【问题描述】:

标题可能有点不对劲。我会正确解释这一点。我将收到一个 DataFrame df,其中一个名为 marker 的列具有意想不到的格式。

有时,我会marker,混合单个marker 或范围marker

marker             place1       place2
45                  PQR           STU
145.0-100           ABC           DEF
267.0-175.8         GHI           KLM

在转换过程中,我需要拆分包含-marker 并变成这样:

marker        firstkm    lastkm    place1       place2
45             45         NaN       PQR           STU
145.0-100      145.0      100       ABC           DEF
267.0-175.8    267.0      175.8     GHI           KLM

我还可以获得以下 DataFrame,其中 all marker 不是一个范围。

marker    place1       place2
145.0      ABC           DEF
267.0      GHI           KLM

有了这段代码:

    #Split marker to temporary dataframe , split_m
    split_m = df.marker.str.split('-', expand=True)
    split_m.columns=['firstkm', 'lastkm'] #hitting error here
    split_m = split_km[['firstkm', 'lastkm']].replace([None], np.nan)

如果 DataFrame 像我上面展示的第一个示例,我可以达到我想要的结果。但是,如果 DataFrame 就像我展示的第二个示例一样,我将无法获得结果。我收到错误:

ValueError:长度不匹配:预期轴有 1 个元素,新值 有2个元素

我了解错误是由于 DataFrame 无法在 lastkm 中输入任何值引起的。但我不知道如何处理..

如果我为第二个 DataFrame 打印 split_m,我会得到这个:

marker     firstkm    
145.0       145.0
267.0       267.0

如何将np.nan 立即分配给lastkm 以产生以下结果:

marker     firstkm   lastkm  
145.0       145.0     NaN
267.0       267.0     NaN

编辑

我遇到的另一种模式:

marker        firstkm      lastkm    place1       place2
45             45           NaN       PQR           STU
145.0-100      145.0        100       ABC           DEF
267.0-175.8    267.0        175.8     GHI           KLM
18.1J          18.1J        Nan       GHI           KLM
P7.991-54.3    P7.991       54.3      GHI           KLM
UPM Ex 0.5     UPM Ex 0.5   NaN       PPP           SSS

UPMEx0.5 仍然可以接受。不区分大小写。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    你可以试试这个:

    # create a copy of the original df, split_m
    split_m = df.copy()
    
    # create the additional required columns with default 'NaN' values
    split_m.insert(1, 'firstkm', np.nan)
    split_m.insert(2, 'lastkm', np.nan)
    
    # unpack the splitted values to the columns. If nothing to unpack
    # for 'lastkm', it will become None
    split_m[['firstkm', 'lastkm']] = df.marker.str.split('-', expand=True)
    # fill None values with np.nan
    split_m.fillna(np.nan, inplace=True)
    
    print(split_m)
    

    输出:

            marker firstkm lastkm place1 place2
    0           45      45    NaN    PQR    STU
    1    145.0-100   145.0    100    ABC    DEF
    2  267.0-175.8   267.0  175.8    GHI    KLM
    3        145.0   145.0    NaN    ABC    DEF
    4        267.0   267.0    NaN    GHI    KLM
    

    改变输入的新场景:

    # tab separated data for read_clipboard()
    # please make sure that you source data 
    # has a separator other than space.
    '''
    marker  place1  place2
    45  PQR STU
    145.0-100   ABC DEF
    267.0-175.8 GHI KLM
    145.0   ABC DEF
    267.0   GHI KLM
    P7.991-54.3 GHI KLM
    UPM Ex 0.5  PPP SSS
    '''
    
    import pandas as pd
    import numpy as np
    
    df = pd.read_clipboard()
    
    # #Split marker to temporary dataframe , split_m
    split_m = df.copy()
    
    # create the additional required columns with default 'NaN' values
    split_m.insert(1, 'firstkm', np.nan)
    split_m.insert(2, 'lastkm', np.nan)
    
    # unpack the splitted values to the columns. If nothing to unpack
    # for 'lastkm', it will become None
    split_m[['firstkm', 'lastkm']] = df.marker.str.split('-', expand=True)
    split_m.fillna(np.nan, inplace=True)
    
    print(split_m)
    

    输出:

            marker     firstkm lastkm place1 place2
    0           45          45    NaN    PQR    STU
    1    145.0-100       145.0    100    ABC    DEF
    2  267.0-175.8       267.0  175.8    GHI    KLM
    3        145.0       145.0    NaN    ABC    DEF
    4        267.0       267.0    NaN    GHI    KLM
    5  P7.991-54.3      P7.991   54.3    GHI    KLM
    6   UPM Ex 0.5  UPM Ex 0.5    NaN    PPP    SSS
    

    【讨论】:

    • 嘿,你的工作正常!但另一个解决方案执行得更快。谢谢!
    • 确定..没问题
    • 重做你的代码并得到这个错误:ValueError: Columns must be same length as key
    • 你能分享你的确切代码吗?也许将其粘贴在问题中?另外,我看到您提到模式发生了变化。如果是这样,代码将不得不更改以采用。
    • 我为您添加到问题中的新场景运行了我的代码,它似乎工作正常。用新的输入更新我的答案。请确保您的源数据由空格以外的分隔符分隔。
    【解决方案2】:

    使用str.extract:

    print (df["marker"].str.extract("(?P<Start>\d+\.?\d+?)-?(?P<End>\d+\.?\d+?)?"))
    
       Start    End
    0     45    NaN
    1  145.0    100
    2  267.0  175.8
    

    【讨论】:

    • 你能解释一下正则表达式的作用吗?这会消除不需要的空格吗?
    • 它首先匹配\d+,它是一个或多个数字,然后是可选的. 和更多digits,以防你有浮点数。然后再跟一个可选的- 加上相同的数字。
    • 公平地说,原始数据最初像“km UPM24.0x”这样的原始数据,我已经去掉了“km”,不管它是干净的列。其中可能包含字母数字的组合跨度>
    • 如果您的原始数据与提供的数据不同,请确保您提供实际样本。从外观上看应该不会有太大变化。
    • 我可以举个例子。请看一看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-29
    • 2021-09-16
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    相关资源
    最近更新 更多