Python,在现有列上创建新列条件

Python,在现有列上创建新列条件,python,pandas,Python,Pandas,在我现有的数据帧df中有3列:A、B、C 我想在A、B、C的基础上再加一列D 逻辑是: if (A == "a"): D = "a" elif (A == "b") and (B in ["B", "C"]): D = "A" elif (C == "c"): D = "c" Note: the value of D can be NaN if all conditions are not satisfied. 有什么优雅而简洁的方法可以添加这个专栏吗?我认为这是最具可

在我现有的数据帧df中有3列:A、B、C

我想在A、B、C的基础上再加一列D

逻辑是:

if (A == "a"):
    D = "a"
elif (A == "b") and (B in ["B", "C"]):
    D = "A"
elif (C == "c"):
    D = "c"
Note: the value of D can be NaN if all conditions are not satisfied.

有什么优雅而简洁的方法可以添加这个专栏吗?

我认为这是最具可读性的方法,但仍然有些简洁

def my_logic(x):
    if x[0] == 'a':
        return 'a'
    elif x[0] == 'b' and x[1] in ('B', 'C'):
        return 'A'
    elif x[2] == 'c':
        return 'c'
    return ''

df['D'] = df[['A', 'B', 'C']].apply(my_logic, axis=1)

我认为这是最具可读性的方法,但仍然有些紧凑

def my_logic(x):
    if x[0] == 'a':
        return 'a'
    elif x[0] == 'b' and x[1] in ('B', 'C'):
        return 'A'
    elif x[2] == 'c':
        return 'c'
    return ''

df['D'] = df[['A', 'B', 'C']].apply(my_logic, axis=1)

这将比if/elif解决方案更快,并且线路更少。然而,它可以说是不可读

df.loc[df.A=="a", "D") = "a"
df.loc[(df.A=="b") & df.B.isin("B", "C"), "D") = "A"
df.loc[(df.C=="c") & ~df.A.isin("a", "A"), "D"] = "c"
df.loc[~df.D.isin("a", "A", "c"), "D"] = np.nan

这将比if/elif解决方案更快,并且线路更少。然而,它可以说是不可读

df.loc[df.A=="a", "D") = "a"
df.loc[(df.A=="b") & df.B.isin("B", "C"), "D") = "A"
df.loc[(df.C=="c") & ~df.A.isin("a", "A"), "D"] = "c"
df.loc[~df.D.isin("a", "A", "c"), "D"] = np.nan

嵌套的位置应该是最快的

np.where(df.A == 'a', 'a', 
         np.where((df.A == 'b') & (df.B.isin(['B','C'])), 'A',
         np.where(df.C == 'c', 'c', np.nan)))
速度测试

# create 100,000 rows of random data
df = pd.DataFrame({'A':np.random.choice(['a','b','c','A','B','C'], 100000, True),
               'B':np.random.choice(['a','b','c','A','B','C'], 100000, True), 
               'C':np.random.choice(['a','b','c','A','B','C'], 100000, True)})

%%timeit 
np.where(df.A == 'a', 'a', 
     np.where((df.A == 'b') & (df.B.isin(['B','C'])), 'A',
     np.where(df.C == 'c', 'c', np.nan)))
10个环路,最佳3个:每个环路33.4毫秒

def my_logic(x):
    if x[0] == 'a':
        return 'a'
    elif x[0] == 'b' and x[1] in ('B', 'C'):
        return 'A'
    elif x[2] == 'c':
        return 'c'
    return ''

%%timeit
df[['A', 'B', 'C']].apply(my_logic, axis=1)
1圈,最好3圈:每圈5.87秒

def my_logic(x):
    if x[0] == 'a':
        return 'a'
    elif x[0] == 'b' and x[1] in ('B', 'C'):
        return 'A'
    elif x[2] == 'c':
        return 'c'
    return ''

%%timeit
df[['A', 'B', 'C']].apply(my_logic, axis=1)

嵌套式where的速度是应用<代码>的175倍,这是最后一种方法。

嵌套式where应该是最快的

np.where(df.A == 'a', 'a', 
         np.where((df.A == 'b') & (df.B.isin(['B','C'])), 'A',
         np.where(df.C == 'c', 'c', np.nan)))
速度测试

# create 100,000 rows of random data
df = pd.DataFrame({'A':np.random.choice(['a','b','c','A','B','C'], 100000, True),
               'B':np.random.choice(['a','b','c','A','B','C'], 100000, True), 
               'C':np.random.choice(['a','b','c','A','B','C'], 100000, True)})

%%timeit 
np.where(df.A == 'a', 'a', 
     np.where((df.A == 'b') & (df.B.isin(['B','C'])), 'A',
     np.where(df.C == 'c', 'c', np.nan)))
10个环路,最佳3个:每个环路33.4毫秒

def my_logic(x):
    if x[0] == 'a':
        return 'a'
    elif x[0] == 'b' and x[1] in ('B', 'C'):
        return 'A'
    elif x[2] == 'c':
        return 'c'
    return ''

%%timeit
df[['A', 'B', 'C']].apply(my_logic, axis=1)
1圈,最好3圈:每圈5.87秒

def my_logic(x):
    if x[0] == 'a':
        return 'a'
    elif x[0] == 'b' and x[1] in ('B', 'C'):
        return 'A'
    elif x[2] == 'c':
        return 'c'
    return ''

%%timeit
df[['A', 'B', 'C']].apply(my_logic, axis=1)

嵌套式where比
apply
快175倍-最后的方法。

可能重复的
apply
的可能重复应该是最后的方法,因为即使是中等大小的数据帧,由于其未矢量化,其速度也可能非常慢。也许问题的一部分在于R中大量的应用函数。Pandas最好是在不了解应用的情况下学习。@TEDPROU在您的评论中的速度测试做得很好!我相信apply对于初学者来说是一个非常好的工具,因为它允许以更可读的格式编写代码。
apply
应该是最后的选择,因为它对于中等大小的数据帧来说速度非常慢,因为它没有矢量化。也许问题的一部分在于R中大量的应用函数。Pandas最好是在不了解应用的情况下学习。@TEDPROU在您的评论中的速度测试做得很好!我相信apply对于初学者来说是一个非常好的工具,因为它允许以更可读的格式编写代码。