根据现有列中的值创建新列

时间:2021-01-14 05:16:10

标签: python-3.x regex pandas dataframe

我想创建一个新列来对某个地址是住宅地址还是非住宅地址进行分类。

下面是原始数据框中的一列:

<头>
建筑物名称
彩云(二)村凤泽楼
玛格丽特公主医院(非住院)

我编写以下代码来创建一个新列,如果字符串“non-residential”在 Building_name 中,它将被归类为 Non-residential,否则将被归类为 Residential。

def build_cat(row):
    if "(non-residential)" not in district_df['Building_name']:
        return ("Residential")
    if '(non-residential)' in district_df['Building_name']:
        return ('Non_residential')

district_df['Building_category'] = district_df.apply(lambda row: build_cat(row), axis =1) 

但是,about 函数将所有内容返回为 Residential。

<头>
建筑物名称 Building_cateory
彩云(二)村凤泽楼 住宅
玛格丽特公主医院(非住院) 住宅

感谢您能否让我知道我的代码有什么问题,或者是否有其他更有效的方法来获得相同的结果。

谢谢。

5 个答案:

答案 0 :(得分:2)

或使用 np.where 作为 python if-else 三元运算符

cond = district_df['Building_name'].str.contains(r'\(non-residential\)')
district_df['Building_cateory'] = np.where(cond, 'Non_residential', 'Residential')

将函数应用到目标列 Building_name

def build_cat(x):
    if "(non-residential)" not in x:
        return "Residential"
    else:
        return 'Non_residential'
district_df['Building_category'] = district_df['Building_name'].map(build_cat)

答案 1 :(得分:2)

我选择添加这个社区维基,以供学习:

在我的 Jupyter Notebook 上,我比较了来自 @MayankPorwal 和 @Ferris 的答案。结果如下:

首先,str.containsnp.where 方法:

import pandas as pd
import numpy as np

df = pd.DataFrame({'Building_name': ['Fung Chak House, Choi Wan (II) Estate', 'Princess Margaret Hospital (non-residential)', 'Fung Chak 1', 'Fung Chak 2 (non-residential)', 'Fung Chak 3']})

df = pd.concat([df] * 10000, ignore_index=True)

def prop():
    df['Building_cateory'] = np.where(df.Building_name.str.contains('non-residential'), 'Non-residential', 'residential')

现在,计时:

%timeit prop()

结果:

81.1 ms ± 15.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

另一方面,map() 方法:

import pandas as pd
import numpy as np

df = pd.DataFrame({'Building_name': ['Fung Chak House, Choi Wan (II) Estate', 'Princess Margaret Hospital (non-residential)', 'Fung Chak 1', 'Fung Chak 2 (non-residential)', 'Fung Chak 3']})

df = pd.concat([df] * 10000, ignore_index=True)

def prop():
    def build_cat(x):
        if "(non-residential)" not in x:
            return "Residential"
        else:
            return 'Non_residential'
    df['Building_category'] = df['Building_name'].map(build_cat)

现在,计时:

%timeit prop()

结果:

15.7 ms ± 1.13 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)

因此,我们有一个明显的赢家!

答案 2 :(得分:1)

尝试以下 pandas 技巧以更快


编辑

不,应用 lambda 更快。

使用 str.contains 方法计时:

2.34 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

使用 apply-lambda 方法计时:

1.08 ms ± 138 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

使用 map() 方法最快

742 µs ± 112 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

请注意,新列 Building_category 是在 #Line 1

之后创建的
import pandas as pd

df = pd.DataFrame({'Building_name': ['Fung Chak House, Choi Wan (II) Estate', 'Princess Margaret Hospital (non-residential)']})

# Line 1
df.loc[df[df['Building_name'].str.contains('(non-residential)')].index, 'Building_category'] = "Non_Residential"

# Line 2
df.loc[df[~df['Building_name'].str.contains('(non-residential)')].index, 'Building_category'] = "Residential"

print(df)

生成的输出:

                                  Building_name Building_category
0         Fung Chak House, Choi Wan (II) Estate       Residential
1  Princess Margaret Hospital (non-residential)   Non_Residential

答案 3 :(得分:1)

使用numpy.where

In [1197]: import numpy as np

In [1198]: df['Building_cateory'] = np.where(df.Building_name.str.contains('non-residential'), 'Non-residential', 'residential')

In [1199]: df
Out[1199]: 
                                  Building_name  Building_cateory
0         Fung Chak House, Choi_Wan (II) Estate       residential
1  Princess Margaret Hospital (non-residential)   Non-residential

答案 4 :(得分:0)

不确定这是最好的方法。但是,关于您得到的意外结果的确切问题,请将您的函数中的 district_df 更改为 row。像这样。 要获得更好的方法,请查看下面的其他答案。克尔。

    def build_cat(row):
        if "(non-residential)" not in row['Building_name']:
            return ("Residential")
        if '(non-residential)' in row['Building_name']:
            return ('Non_residential')
    
    district_df['Building_category'] = district_df.apply(lambda row: build_cat(row), axis =1) 
    ```