根据其他列的值创建新列/在 Pandas 中按行应用多列函数

2024-11-29 08:42:00
admin
原创
3
摘要:问题描述:我想将我的自定义函数(它使用 if-else 阶梯)应用于数据框每行的这六列(,,ERI_Hispanic,ERI_AmerInd_AKNatv,ERI_Asian)ERI_Black_Afr.Amer。ERI_HI_PacIsl`ERI_White`我尝试了其他问题中的不同方法,但似乎仍然找不到我...

问题描述:

我想将我的自定义函数(它使用 if-else 阶梯)应用于数据框每行的这六列(,,ERI_HispanicERI_AmerInd_AKNatvERI_AsianERI_Black_Afr.AmerERI_HI_PacIsl`ERI_White`

我尝试了其他问题中的不同方法,但似乎仍然找不到我的问题的正确答案。关键在于,如果一个人被算作西班牙裔,他们就不能被算作其他种族。即使他们在另一个种族列中有一个“1”,他们仍然被视为西班牙裔,而不是两个或多个种族。同样,如果所有 ERI 列的总和大于 1,他们就会被算作两个或多个种族,不能被算作一个独特的种族(西班牙裔除外)。

这几乎就像对每一行进行 for 循环,如果每条记录都符合条件,则将它们添加到一个列表中并从原始列表中删除。

从下面的数据框中,我需要根据 SQL 中的以下规范计算一个新列:

标准

IF [ERI_Hispanic] = 1 THEN RETURN “Hispanic”
ELSE IF SUM([ERI_AmerInd_AKNatv] + [ERI_Asian] + [ERI_Black_Afr.Amer] + [ERI_HI_PacIsl] + [ERI_White]) > 1 THEN RETURN “Two or More”
ELSE IF [ERI_AmerInd_AKNatv] = 1 THEN RETURN “A/I AK Native”
ELSE IF [ERI_Asian] = 1 THEN RETURN “Asian”
ELSE IF [ERI_Black_Afr.Amer] = 1 THEN RETURN “Black/AA”
ELSE IF [ERI_HI_PacIsl] = 1 THEN RETURN “Haw/Pac Isl.”
ELSE IF [ERI_White] = 1 THEN RETURN “White”

注释:如果西班牙裔的 ERI 标记为真 (1),则该员工被归类为“西班牙裔”

注释:如果超过 1 个非西班牙裔 ERI 标志为真,则返回“两个或更多”

数据框

     lname          fname       rno_cd  eri_afr_amer    eri_asian   eri_hawaiian    eri_hispanic    eri_nat_amer    eri_white   rno_defined
0    MOST           JEFF        E       0               0           0               0               0               1           White
1    CRUISE         TOM         E       0               0           0               1               0               0           White
2    DEPP           JOHNNY              0               0           0               0               0               1           Unknown
3    DICAP          LEO                 0               0           0               0               0               1           Unknown
4    BRANDO         MARLON      E       0               0           0               0               0               0           White
5    HANKS          TOM         0                       0           0               0               0               1           Unknown
6    DENIRO         ROBERT      E       0               1           0               0               0               1           White
7    PACINO         AL          E       0               0           0               0               0               1           White
8    WILLIAMS       ROBIN       E       0               0           1               0               0               0           White
9    EASTWOOD       CLINT       E       0               0           0               0               0               1           White

解决方案 1:

好的,这个有两个步骤 - 第一步是编写一个执行您想要的翻译的函数 - 我根据您的伪代码整理了一个示例:

def label_race(row):
   if row['eri_hispanic'] == 1:
      return 'Hispanic'
   if row['eri_afr_amer'] + row['eri_asian'] + row['eri_hawaiian'] + row['eri_nat_amer'] + row['eri_white'] > 1:
      return 'Two Or More'
   if row['eri_nat_amer'] == 1:
      return 'A/I AK Native'
   if row['eri_asian'] == 1:
      return 'Asian'
   if row['eri_afr_amer'] == 1:
      return 'Black/AA'
   if row['eri_hawaiian'] == 1:
      return 'Haw/Pac Isl.'
   if row['eri_white'] == 1:
      return 'White'
   return 'Other'

您可能想要仔细研究一下,但是它似乎可以解决问题 - 请注意,进入函数的参数被视为标记为“row”的 Series 对象。

接下来,使用 Pandas 中的 apply 函数来应用该函数 - 例如

df.apply(label_race, axis=1)

注意axis=1说明符,这意味着应用是在行而不是列级别完成的。结果如下:

0           White
1        Hispanic
2           White
3           White
4           Other
5           White
6     Two Or More
7           White
8    Haw/Pac Isl.
9           White

如果您对这些结果满意,请再次运行它,并将结果保存到原始数据框的新列中。

df['race_label'] = df.apply(label_race, axis=1)

得到的数据框如下所示(向右滚动即可看到新列):

      lname   fname rno_cd  eri_afr_amer  eri_asian  eri_hawaiian   eri_hispanic  eri_nat_amer  eri_white rno_defined    race_label
0      MOST    JEFF      E             0          0             0              0             0          1       White         White
1    CRUISE     TOM      E             0          0             0              1             0          0       White      Hispanic
2      DEPP  JOHNNY    NaN             0          0             0              0             0          1     Unknown         White
3     DICAP     LEO    NaN             0          0             0              0             0          1     Unknown         White
4    BRANDO  MARLON      E             0          0             0              0             0          0       White         Other
5     HANKS     TOM    NaN             0          0             0              0             0          1     Unknown         White
6    DENIRO  ROBERT      E             0          1             0              0             0          1       White   Two Or More
7    PACINO      AL      E             0          0             0              0             0          1       White         White
8  WILLIAMS   ROBIN      E             0          0             1              0             0          0       White  Haw/Pac Isl.
9  EASTWOOD   CLINT      E             0          0             0              0             0          1       White         White

解决方案 2:

由于这是 Google 搜索“pandas new column from others”的第一个结果,因此这里有一个简单的例子:

import pandas as pd

# make a simple dataframe
df = pd.DataFrame({'a':[1,2], 'b':[3,4]})
df
#    a  b
# 0  1  3
# 1  2  4

# create an unattached column with an index
df.apply(lambda row: row.a + row.b, axis=1)
# 0    4
# 1    6

# do same but attach it to the dataframe
df['c'] = df.apply(lambda row: row.a + row.b, axis=1)
df
#    a  b  c
# 0  1  3  4
# 1  2  4  6

如果你得到了SettingWithCopyWarning你也可以这样做:

col = df.apply(lambda row: row.a + row.b, axis=1)
df = df.assign(c=col.values) # assign values to column 'c'

资料来源:https ://stackoverflow.com/a/12555510/243392

如果列名中包含空格,则可以使用如下语法:

df = df.assign(**{'some column name': col.values})

这是apply和assign的文档。

解决方案 3:

上述答案完全正确,但存在一个矢量化解决方案,形式为numpy.select。这允许您定义条件,然后为这些条件定义输出,比使用更有效apply


首先,定义条件:

conditions = [
    df['eri_hispanic'] == 1,
    df[['eri_afr_amer', 'eri_asian', 'eri_hawaiian', 'eri_nat_amer', 'eri_white']].sum(1).gt(1),
    df['eri_nat_amer'] == 1,
    df['eri_asian'] == 1,
    df['eri_afr_amer'] == 1,
    df['eri_hawaiian'] == 1,
    df['eri_white'] == 1,
]

现在,定义相应的输出:

outputs = [
    'Hispanic', 'Two Or More', 'A/I AK Native', 'Asian', 'Black/AA', 'Haw/Pac Isl.', 'White'
]

最后,使用numpy.select

res = np.select(conditions, outputs, 'Other')
pd.Series(res)
0           White
1        Hispanic
2           White
3           White
4           Other
5           White
6     Two Or More
7           White
8    Haw/Pac Isl.
9           White
dtype: object

为什么要numpy.select使用apply?以下是一些性能检查:

df = pd.concat([df]*1000)

In [42]: %timeit df.apply(lambda row: label_race(row), axis=1)
1.07 s ± 4.16 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [44]: %%timeit
    ...: conditions = [
    ...:     df['eri_hispanic'] == 1,
    ...:     df[['eri_afr_amer', 'eri_asian', 'eri_hawaiian', 'eri_nat_amer', 'eri_white']].sum(1).gt(1),
    ...:     df['eri_nat_amer'] == 1,
    ...:     df['eri_asian'] == 1,
    ...:     df['eri_afr_amer'] == 1,
    ...:     df['eri_hawaiian'] == 1,
    ...:     df['eri_white'] == 1,
    ...: ]
    ...:
    ...: outputs = [
    ...:     'Hispanic', 'Two Or More', 'A/I AK Native', 'Asian', 'Black/AA', 'Haw/Pac Isl.', 'White'
    ...: ]
    ...:
    ...: np.select(conditions, outputs, 'Other')
    ...:
    ...:
3.09 ms ± 17 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

使用numpy.select可以大大提高我们的性能,并且随着数据的增长,差异只会增加。

解决方案 4:

.apply()接受一个函数作为第一个参数;按label_race如下方式传入该函数:

df['race_label'] = df.apply(label_race, axis=1)

您不需要创建 lambda 函数来传递函数。

解决方案 5:

试试这个,

df.loc[df['eri_white']==1,'race_label'] = 'White'
df.loc[df['eri_hawaiian']==1,'race_label'] = 'Haw/Pac Isl.'
df.loc[df['eri_afr_amer']==1,'race_label'] = 'Black/AA'
df.loc[df['eri_asian']==1,'race_label'] = 'Asian'
df.loc[df['eri_nat_amer']==1,'race_label'] = 'A/I AK Native'
df.loc[(df['eri_afr_amer'] + df['eri_asian'] + df['eri_hawaiian'] + df['eri_nat_amer'] + df['eri_white']) > 1,'race_label'] = 'Two Or More'
df.loc[df['eri_hispanic']==1,'race_label'] = 'Hispanic'
df['race_label'].fillna('Other', inplace=True)

输出:

     lname   fname rno_cd  eri_afr_amer  eri_asian  eri_hawaiian  \n0      MOST    JEFF      E             0          0             0   
1    CRUISE     TOM      E             0          0             0   
2      DEPP  JOHNNY    NaN             0          0             0   
3     DICAP     LEO    NaN             0          0             0   
4    BRANDO  MARLON      E             0          0             0   
5     HANKS     TOM    NaN             0          0             0   
6    DENIRO  ROBERT      E             0          1             0   
7    PACINO      AL      E             0          0             0   
8  WILLIAMS   ROBIN      E             0          0             1   
9  EASTWOOD   CLINT      E             0          0             0   

   eri_hispanic  eri_nat_amer  eri_white rno_defined    race_label  
0             0             0          1       White         White  
1             1             0          0       White      Hispanic  
2             0             0          1     Unknown         White  
3             0             0          1     Unknown         White  
4             0             0          0       White         Other  
5             0             0          1     Unknown         White  
6             0             0          1       White   Two Or More  
7             0             0          1       White         White  
8             0             0          0       White  Haw/Pac Isl.  
9             0             0          1       White         White 

.loc代替apply

它提高了矢量化。

.loc以简单的方式工作,根据条件屏蔽行,将值应用于冻结行。

欲了解更多详情,请访问.loc 文档

性能指标:

一般答案:

def label_race (row):
   if row['eri_hispanic'] == 1 :
      return 'Hispanic'
   if row['eri_afr_amer'] + row['eri_asian'] + row['eri_hawaiian'] + row['eri_nat_amer'] + row['eri_white'] > 1 :
      return 'Two Or More'
   if row['eri_nat_amer'] == 1 :
      return 'A/I AK Native'
   if row['eri_asian'] == 1:
      return 'Asian'
   if row['eri_afr_amer']  == 1:
      return 'Black/AA'
   if row['eri_hawaiian'] == 1:
      return 'Haw/Pac Isl.'
   if row['eri_white'] == 1:
      return 'White'
   return 'Other'

df=pd.read_csv('dataser.csv')
df = pd.concat([df]*1000)

%timeit df.apply(lambda row: label_race(row), axis=1)

每循环 1.15 秒 ± 46.5 毫秒(7 次运行的平均值 ± 标准差,每次 1 个循环)

我的建议答案:

def label_race(df):
    df.loc[df['eri_white']==1,'race_label'] = 'White'
    df.loc[df['eri_hawaiian']==1,'race_label'] = 'Haw/Pac Isl.'
    df.loc[df['eri_afr_amer']==1,'race_label'] = 'Black/AA'
    df.loc[df['eri_asian']==1,'race_label'] = 'Asian'
    df.loc[df['eri_nat_amer']==1,'race_label'] = 'A/I AK Native'
    df.loc[(df['eri_afr_amer'] + df['eri_asian'] + df['eri_hawaiian'] + df['eri_nat_amer'] + df['eri_white']) > 1,'race_label'] = 'Two Or More'
    df.loc[df['eri_hispanic']==1,'race_label'] = 'Hispanic'
    df['race_label'].fillna('Other', inplace=True)
df=pd.read_csv('s22.csv')
df = pd.concat([df]*1000)

%timeit label_race(df)

每循环 24.7 毫秒 ± 1.7 毫秒(7 次运行的平均值 ± 标准差,每次 10 次循环)

解决方案 6:

如果我们检查它的源代码,apply()它是 Python for 循环的语法糖(通过类apply_series_generator()的方法FrameApply)。因为它有 pandas 开销,所以它通常比 Python 循环慢。

尽可能使用优化(矢量化)方法。如果必须使用循环,请使用@numba.jit装饰器。

  1. 不要将其用作apply()if-else 阶梯


df.apply()几乎是 pandas 中最慢的实现方式。如user3483203和Mohamed Thasin ah的回答所示,取决于数据帧大小,np.select()可能比生成相同输出df.loc快 50-300 倍。df.apply()

事实上,使用模块中的装饰器apply()的循环实现(与 类似)比和快(约 50-60%)。1@jit`numbadf.locnp.select`

Numba 适用于 numpy 数组,因此在使用jit装饰器之前,您需要将数据框转换为 numpy 数组。然后通过循环检查条件,在预初始化的空数组中填充值。由于 numpy 数组没有列名,因此您必须在循环中通过其索引访问列。与 中的 if-else 阶梯相比,jitted 函数中最不方便的部分apply()是通过其索引访问列。否则,它的实现几乎相同。

import numpy as np
import numba as nb
@nb.jit(nopython=True)
def conditional_assignment(arr, res):    
    length = len(arr)
    for i in range(length):
        if arr[i][3] == 1:
            res[i] = 'Hispanic'
        elif arr[i][0] + arr[i][1] + arr[i][2] + arr[i][4] + arr[i][5] > 1:
            res[i] = 'Two Or More'
        elif arr[i][0]  == 1:
            res[i] = 'Black/AA'
        elif arr[i][1] == 1:
            res[i] = 'Asian'
        elif arr[i][2] == 1:
            res[i] = 'Haw/Pac Isl.'
        elif arr[i][4] == 1:
            res[i] = 'A/I AK Native'
        elif arr[i][5] == 1:
            res[i] = 'White'
        else:
            res[i] = 'Other'
    return res

# the columns with the boolean data
cols = [c for c in df.columns if c.startswith('eri_')]
# initialize an empty array to be filled in a loop
# for string dtype arrays, we need to know the length of the longest string
# and use it to set the dtype
res = np.empty(len(df), dtype=f"<U{len('A/I AK Native')}")
# pass the underlying numpy array of `df[cols]` into the jitted function
df['rno_defined'] = conditional_assignment(df[cols].values, res)

  1. 不要用于apply()数字运算


如果需要通过添加两列来添加新行,你的第一反应可能是这样写

df['c'] = df.apply(lambda row: row['a'] + row['b'], axis=1)

sum(axis=1)但不是这样做,而是使用方法(+如果只有几列,则使用运算符)逐行添加:

df['c'] = df[['a','b']].sum(axis=1)
# equivalently
df['c'] = df['a'] + df['b']

根据数据框的大小,sum(1)可能比快 100 倍apply()

事实上,你几乎永远不需要apply()对 pandas 数据框进行数字运算,因为它已经针对大多数运算优化了方法:加法()、sum(1)减法(sub()diff())、乘法(prod(1))、除法(div()/)、幂(pow()>、、、、、、、等都可以在整个数据框上执行,而无需。>=`==%//&|`apply()

例如,假设您想使用以下规则创建一个新列:

IF [colC] > 0 THEN RETURN [colA] * [colB]
ELSE RETURN [colA] / [colB]

使用优化的 pandas 方法,可以写成

df['new'] = df[['colA','colB']].prod(1).where(df['colC']>0, df['colA'] / df['colB'])

等效apply()解决方案是:

df['new'] = df.apply(lambda row: row.colA * row.colB if row.colC > 0 else row.colA / row.colB, axis=1)

对于具有 20k 行的数据帧,使用优化方法的方法比等效方法快 250 倍apply()。这种差距只会随着数据大小的增加而增加(对于具有 1 百万行的数据帧,它快 365 倍),并且时间差异将变得越来越明显。2


1:在下面的结果中,我使用 24 百万行的数据框(这是我可以在我的机器上构建的最大框架)展示了这三种方法的性能。对于较小的框架,numba-jitted 函数的运行速度也比其他两个函数至少快 50%(你可以自己检查一下)。

def pd_loc(df):
    df['rno_defined'] = 'Other'
    df.loc[df['eri_nat_amer'] == 1, 'rno_defined'] = 'A/I AK Native'
    df.loc[df['eri_asian'] == 1, 'rno_defined'] = 'Asian'
    df.loc[df['eri_afr_amer'] == 1, 'rno_defined'] = 'Black/AA'
    df.loc[df['eri_hawaiian'] == 1, 'rno_defined'] = 'Haw/Pac Isl.'
    df.loc[df['eri_white'] == 1, 'rno_defined'] = 'White'
    df.loc[df[['eri_afr_amer', 'eri_asian', 'eri_hawaiian', 'eri_nat_amer', 'eri_white']].sum(1) > 1, 'rno_defined'] = 'Two Or More'
    df.loc[df['eri_hispanic'] == 1, 'rno_defined'] = 'Hispanic'
    return df

def np_select(df):
    conditions = [df['eri_hispanic'] == 1,
                  df[['eri_afr_amer', 'eri_asian', 'eri_hawaiian', 'eri_nat_amer', 'eri_white']].sum(1).gt(1),
                  df['eri_nat_amer'] == 1,
                  df['eri_asian'] == 1,
                  df['eri_afr_amer'] == 1,
                  df['eri_hawaiian'] == 1,
                  df['eri_white'] == 1]
    outputs = ['Hispanic', 'Two Or More', 'A/I AK Native', 'Asian', 'Black/AA', 'Haw/Pac Isl.', 'White']
    df['rno_defined'] = np.select(conditions, outputs, 'Other')
    return df


@nb.jit(nopython=True)
def conditional_assignment(arr, res):
    
    length = len(arr)
    for i in range(length):
        if arr[i][3] == 1 :
            res[i] = 'Hispanic'
        elif arr[i][0] + arr[i][1] + arr[i][2] + arr[i][4] + arr[i][5] > 1 :
            res[i] = 'Two Or More'
        elif arr[i][0]  == 1:
            res[i] = 'Black/AA'
        elif arr[i][1] == 1:
            res[i] = 'Asian'
        elif arr[i][2] == 1:
            res[i] = 'Haw/Pac Isl.'
        elif arr[i][4] == 1 :
            res[i] = 'A/I AK Native'
        elif arr[i][5] == 1:
            res[i] = 'White'
        else:
            res[i] = 'Other'
            
    return res

def nb_loop(df):
    cols = [c for c in df.columns if c.startswith('eri_')]
    res = np.empty(len(df), dtype=f"<U{len('A/I AK Native')}")
    df['rno_defined'] = conditional_assignment(df[cols].values, res)
    return df

# df with 24mil rows
n = 4_000_000
df = pd.DataFrame({
    'eri_afr_amer': [0, 0, 0, 0, 0, 0]*n, 
    'eri_asian': [1, 0, 0, 0, 0, 0]*n, 
    'eri_hawaiian': [0, 0, 0, 1, 0, 0]*n, 
    'eri_hispanic': [0, 1, 0, 0, 1, 0]*n, 
    'eri_nat_amer': [0, 0, 0, 0, 1, 0]*n, 
    'eri_white': [0, 0, 1, 1, 0, 0]*n
}, dtype='int8')
df.insert(0, 'name', ['MOST', 'CRUISE', 'DEPP', 'DICAP', 'BRANDO', 'HANKS']*n)

%timeit nb_loop(df)
# 5.23 s ± 45.2 ms per loop (mean ± std. dev. of 10 runs, 10 loops each)

%timeit pd_loc(df)
# 7.97 s ± 28.8 ms per loop (mean ± std. dev. of 10 runs, 10 loops each)

%timeit np_select(df)
# 8.5 s ± 39.6 ms per loop (mean ± std. dev. of 10 runs, 10 loops each)

2:在下面的结果中,我分别使用 20k 行和 100 万行的数据框展示了这两种方法的性能。对于较小的帧,差距较小,因为优化方法在apply()循环时会产生开销。随着帧大小的增加,相对于代码的整体运行时间,矢量化开销成本会减少,而apply()循环仍是帧上的循环。

n = 20_000 # 1_000_000
df = pd.DataFrame(np.random.rand(n,3)-0.5, columns=['colA','colB','colC'])

%timeit df[['colA','colB']].prod(1).where(df['colC']>0, df['colA'] / df['colB'])
# n = 20000: 2.69 ms ± 23.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# n = 1000000: 86.2 ms ± 441 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit df.apply(lambda row: row.colA * row.colB if row.colC > 0 else row.colA / row.colB, axis=1)
# n = 20000: 679 ms ± 33.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# n = 1000000: 31.5 s ± 587 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

解决方案 7:

根据标准的复杂性选择方法

对于下面的例子 - 为了展示新列的多种类型的规则 - 我们将假设一个 DataFrame 有列'red''green''blue',包含范围从 0 到 1 的浮点值。

一般情况:.apply

只要计算新值的必要逻辑可以写成同一行中其他值的函数,我们就可以使用的方法来获得所需的结果。编写函数使其接受单个参数,即输入的单个行:.apply`DataFrame`

def as_hex(value):
    # clamp to avoid rounding errors etc.
    return min(max(0, int(value * 256)), 255)

def hex_color(row):
    r, g, b = as_hex(row['red']), as_hex(row['green']), as_hex(row['blue'])
    return f'#{r:02x}{g:02x}{b:02x}'

函数本身(不要在名称后写括号)传递给.apply,并指定axis=1(意味着向分类函数提供,以便计算- 而不是相反)。因此:

df['hex_color'] = df.apply(hex_color, axis=1)

请注意,包装lambda没有必要的,因为我们没有绑定任何参数或以其他方式修改函数。

.apply步骤是必需的,因为转换函数本身不是矢量化的。因此,像这样的简单方法df['color'] = hex_color(df)将不起作用(示例问题)。

此工具功能强大,但效率低下。为获得最佳性能,请在适用的情况下使用更具体的方法

带条件的多项选择:numpy.select或用df.loc或重复赋值df.where

假设我们对颜色值进行阈值处理,并计算粗略的颜色名称,如下所示:

def additive_color(row):
    # Insert here: logic that takes values from the `row` and computes
    # the desired cell value for the new column in that row.
    # The `row` is an ordinary `Series` object representing a row of the
    # original `DataFrame`; it can be indexed with column names, thus:
    if row['red'] > 0.5:
        if row['green'] > 0.5:
            return 'white' if row['blue'] > 0.5 else 'yellow'
        else:
            return 'magenta' if row['blue'] > 0.5 else 'red'
    elif row['green'] > 0.5:
        return 'cyan' if row['blue'] > 0.5 else 'green'
    else:
        return 'blue' if row['blue'] > 0.5 else 'black'

在这种情况下 - 分类功能将是if/else阶梯,或3.10 及更高版本中的match/ case- 我们可以使用 获得更快的性能numpy.select

这种方法的工作原理非常不同。首先,计算每个条件适用的数据掩码:

black = (df['red'] <= 0.5) & (df['green'] <= 0.5) & (df['blue'] <= 0.5)
white = (df['red'] > 0.5) & (df['green'] > 0.5) & (df['blue'] > 0.5)

要调用numpy.select,我们需要两个并行序列 - 一个是条件,另一个是相应的值:

df['color'] = np.select(
    [white, black],
    ['white', 'black'],
    'colorful'
)

可选的第三个参数指定当所有条件均不满足时使用的值。(作为练习:填写剩余条件,并尝试不使用第三个参数。)

类似的方法是根据每个条件进行重复赋值。分配默认值,然后使用df.loc为每个条件分配具体值:

df['color'] = 'colorful'
df.loc[white, 'color'] = 'white'
df.loc[black, 'color'] = 'black'

另外,df.where可用于进行赋值。但是,df.where像这样使用 ,会在条件不满足的地方分配指定的值,因此必须反转条件:

df['color'] = 'colorful'
df['color'] = df['color'].where(~white, 'white').where(~black, 'black')

简单的数学运算:内置数学运算符和广播

例如,apply基于 - 的方法如下:

def brightness(row):
    return row['red'] * .299 + row['green'] * .587 + row['blue'] * .114

df['brightness'] = df.apply(brightness, axis=1)

可以通过广播操作符来编写,以获得更好的性能(并且也更简单):

df['brightness'] = df['red'] * .299 + df['green'] * .587 + df['blue'] * .114

作为练习,这里是按照这种方式重做的第一个例子:

def as_hex(column):
    scaled = (column * 256).astype(int)
    clamped = scaled.where(scaled >= 0, 0).where(scaled <= 255, 255)
    return clamped.apply(lambda i: f'{i:02x}')

df['hex_color'] = '#' + as_hex(df['red']) + as_hex(df['green']) + as_hex(df['blue'])

我找不到将整数值格式化为十六进制字符串的矢量化等效方法,因此.apply这里仍在内部使用 - 这意味着全速惩罚仍然发挥作用。不过,这展示了一些通用技术。

有关更多详细信息和示例,请参阅cottontail 的回答。

解决方案 8:

还有另一种(易于推广的)方法,其基石是pandas.DataFrame.idxmax。首先,易于推广的序言。

# Indeed, all your conditions boils down to the following
_gt_1_key = 'two_or_more'
_lt_1_key = 'other'

# The "dictionary-based" if-else statements
labels = {
    _gt_1_key     : 'Two Or More',
    'eri_hispanic': 'Hispanic',
    'eri_nat_amer': 'A/I AK Native',
    'eri_asian'   : 'Asian',
    'eri_afr_amer': 'Black/AA',
    'eri_hawaiian': 'Haw/Pac Isl.',
    'eri_white'   : 'White',  
    _lt_1_key     : 'Other',
}

# The output-driving 1-0 matrix
mat = df.filter(regex='^eri_').copy()  # `~.copy` to avoid `SettingWithCopyWarning`

...最后,以矢量化的方式

mat[_gt_1_key] = gt1 = mat.sum(axis=1)
mat[_lt_1_key] = gt1.eq(0).astype(int)
race_label     = mat.idxmax(axis=1).map(labels)

在哪里

>>> race_label
0           White
1        Hispanic
2           White
3           White
4           Other
5           White
6     Two Or More
7           White
8    Haw/Pac Isl.
9           White
dtype: object

这是一个pandas.Series您可以轻松托管的实例df,即执行df['race_label'] = race_label

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   649  
  如何借鉴华为IPD体系优化企业研发?在当今竞争激烈的市场环境中,企业要想保持技术领先和产品竞争力,必须拥有一套高效且严谨的研发管理体系。华为作为全球领先的ICT解决方案提供商,其集成产品开发(IPD, Integrated Product Development)体系与质量管理体系(如ISO 9000系列)的融合实践,...
IPD项目管理   0  
  IPD流程图的7种经典绘制方法详解在产品开发领域,集成产品开发(Integrated Product Development,简称IPD)流程被广泛应用,以提高产品开发的效率和质量。IPD流程图作为这一流程的可视化工具,其绘制方法至关重要。本文将详细介绍七种经典的IPD流程图绘制方法,帮助项目管理人员和团队更好地理解和...
IPD研发管理体系   0  
  IPD流程:企业创新管理的核心引擎在当今快速变化的市场环境中,企业要想持续保持竞争力,就必须不断进行创新。而IPD(Integrated Product Development,集成产品开发)流程作为一种先进的产品开发管理模式,正逐渐成为众多企业提升创新能力、加速产品上市速度、降低开发成本的重要选择。本文将深入探讨IP...
IPD管理   0  
  IPD流程与传统产品开发流程的概述在产品开发领域,企业不断寻求高效、系统的管理方法以确保产品能够顺利从概念转化为市场成功的产品。集成产品开发(Integrated Product Development,简称IPD)流程与传统产品开发流程是两种截然不同的管理理念和方法。传统产品开发流程往往以职能部门为核心,各部门按顺序...
IPD流程中PDCP是什么意思   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用