【问题标题】:Assign value to a column based of other columns from the same pandas dataframe为基于同一熊猫数据框中其他列的列分配值
【发布时间】:2017-03-03 15:41:44
【问题描述】:

使用数据框,我有一列,称为TM52_fail

2
1
-
1 & 2
1 & 2 & 3
-
-
3
etc.

我想创建一个名为TM52_fail_norm 的附加列,其内容取决于TM52_fail 列的内容。 我的尝试(包括条件填充):

def str_to_number(x):
    if x=="1" or x=="2" or x=="3":
        return 1
    elif x=="1 & 2" or x=="2 & 3" or x=="1 & 3":
        return 2
    elif x=="1 & 2 & 3":
        return 3
    else:
        return 0

df['TM52_fail_norm'] = ""
df['TM52_fail_norm'].apply(lambda x: str_to_number(x for x in df['TM52_fail']))

返回一个空列(我推测是df['TM52_fail_norm'] = "" 的结果)。

【问题讨论】:

    标签: python pandas lambda conditional-statements


    【解决方案1】:

    我认为您需要通过astype 转换为字符串,然后应用函数str_to_number

    df['new'] = df['TM52_fail_norm'].astype(str).apply(str_to_number)
    print (df)
      TM52_fail_norm  new
    0              2    1
    1              1    1
    2              -    0
    3          1 & 2    2
    4      1 & 2 & 3    3
    5              -    0
    6              -    0
    7              3    1
    

    map by dict 的另一个解决方案,最后需要fillna by 0 并转换为int

    d = {'1':1,'2':1,'3':1,'1 & 2':2, '2 & 3':2, '1 & 3':2,'1 & 2 & 3':3}
    
    df['new'] = df['TM52_fail_norm'].map(d)
    df['new'] = df['new'].fillna(0).astype(int)
    print (df)
      TM52_fail_norm  new
    0              2    1
    1              1    1
    2              -    0
    3          1 & 2    2
    4      1 & 2 & 3    3
    5              -    0
    6              -    0
    7              3    1
    

    时间安排

    #[800000 rows x 1 columns]
    df = pd.concat([df]*100000).reset_index(drop=True)
    
    In [315]: %timeit (jez1(df))
    10 loops, best of 3: 63 ms per loop
    
    In [316]: %timeit (df['TM52_fail_norm'].astype(str).apply(str_to_number))
    1 loop, best of 3: 518 ms per loop
    
    #http://stackoverflow.com/a/40176883/2901002
    In [345]: %timeit (df.TM52_fail_norm.str.count('\d+'))
    1 loop, best of 3: 707 ms per loop
    
    
    def jez1(df):
        d = {'1':1,'2':1,'3':1,'1 & 2':2, '2 & 3':2, '1 & 3':2,'1 & 2 & 3':3}
    
        df['new'] = df['TM52_fail_norm'].map(d)
        df['new'] = df['new'].fillna(0).astype(int)
        return (df)
    
    print (jez1(df))
    

    【讨论】:

    • 谢谢。我认为第二种解决方案可以更快。
    【解决方案2】:

    TL;DR:df.TM52_fail.str.count('\d+')

    看来你真正想要的是数位数。在这里,pandas 的 .str 访问器方法(docssummary of .str methods)真的很有帮助!

    我想TM52_fail 的数据类型为str;否则,您可以按照@jezrael 的建议使用.astype(str) 进行投射:

    # setup
    import pandas as pd
    df = pd.DataFrame({'TM52_fail':[
        "2", "1", "", "1 & 2", "1 & 2 & 3", "", "", "3"]})
    
    # Use regex \d+ to find 1 or more consecutive digits
    df['TM52_fail_norm2'] = df.TM52_fail.str.count('\d+')
    

    时间

    Regex: 155 µs per loop
     jez1: 999 µs per loop
    

    【讨论】:

    • 是的,它在小数据帧中更快,但在更大的数据帧中最慢。请参阅我的时间更新。但我认为这是一个很好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2019-09-08
    • 2021-10-08
    • 2016-01-27
    • 1970-01-01
    • 2018-02-15
    • 2020-05-31
    • 2019-09-30
    • 1970-01-01
    相关资源
    最近更新 更多