Pandas/Python: 根据另一列中的值设置一列的值
Pandas/Python: Set value of one column based on value in another column
我需要根据 Pandas 数据框中另一列的值设置一列的值。这是逻辑:
if df['c1'] == 'Value':
df['c2'] = 10
else:
df['c2'] = df['c3']
我无法让它做我想做的事,即简单地创建一个具有新值的列(或更改现有列的值:任何一个都适合我)。
如果我尝试 运行 上面的代码,或者如果我将它写成一个函数并使用 apply 方法,我会得到以下结果:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
尝试:
df['c2'] = df['c1'].apply(lambda x: 10 if x == 'Value' else x)
一种方法是使用 .loc
的索引。
例子
由于没有示例数据框,我会在这里补一个:
import numpy as np
import pandas as pd
df = pd.DataFrame({'c1': list('abcdefg')})
df.loc[5, 'c1'] = 'Value'
>>> df
c1
0 a
1 b
2 c
3 d
4 e
5 Value
6 g
假设您想要创建一个新列 c2
,等同于 c1
,除了 c1
是 Value
,在这种情况下,您想将其分配给 10:
首先,您可以创建一个新列 c2
,并将其设置为等同于 c1
,使用以下两行之一(它们基本上做同样的事情):
df = df.assign(c2 = df['c1'])
# OR:
df['c2'] = df['c1']
然后,使用 .loc
找到 c1
等于 'Value'
的所有索引,并在这些索引处在 c2
中分配您想要的值:
df.loc[df['c1'] == 'Value', 'c2'] = 10
你最终得到这个:
>>> df
c1 c2
0 a a
1 b b
2 c c
3 d d
4 e e
5 Value 10
6 g g
如果正如您在问题中所建议的那样,有时您可能只想替换您已有的列中的值,而不是创建一个新列,那么只需跳过列创建,并执行以下操作:
df['c1'].loc[df['c1'] == 'Value'] = 10
# or:
df.loc[df['c1'] == 'Value', 'c1'] = 10
给你:
>>> df
c1
0 a
1 b
2 c
3 d
4 e
5 10
6 g
您可以使用 np.where()
根据指定条件设置值:
#df
c1 c2 c3
0 4 2 1
1 8 7 9
2 1 5 8
3 3 3 5
4 3 6 8
现在根据您的情况更改(或设置)第 ['c2']
列中的值。
df['c2'] = np.where(df.c1 == 8,'X', df.c3)
c1 c2 c3
0 4 1 1
1 8 X 9
2 1 8 8
3 3 5 5
4 3 8 8
我建议分两步进行:
# set fixed value to 'c2' where the condition is met
df.loc[df['c1'] == 'Value', 'c2'] = 10
# copy value from 'c3' to 'c2' where the condition is NOT met
df.loc[df['c1'] != 'Value', 'c2'] = df[df['c1'] != 'Value', 'c3']
您可以使用 pandas.DataFrame.mask
添加几乎任意数量的条件:
data = {'a': [1,2,3,4,5], 'b': [6,8,9,10,11]}
d = pd.DataFrame.from_dict(data, orient='columns')
c = {'c1': (2, 'Value1'), 'c2': (3, 'Value2'), 'c3': (5, d['b'])}
d['new'] = np.nan
for value in c.values():
d['new'].mask(d['a'] == value[0], value[1], inplace=True)
d['new'] = d['new'].fillna('Else')
d
输出:
a b new
0 1 6 Else
1 2 8 Value1
2 3 9 Value2
3 4 10 Else
4 5 11 11
如果您有 small/medium 数据框,请尝试 df.apply(),
df['c2'] = df.apply(lambda x: 10 if x['c1'] == 'Value' else x['c1'], axis = 1)
否则,如果你有一个大数据框,请遵循上面评论中提到的切片技术。
注意反转选择的波浪线。它使用 pandas 方法(即比 if
/else
更快)。
df.loc[(df['c1'] == 'Value'), 'c2'] = 10
df.loc[~(df['c1'] == 'Value'), 'c2'] = df['c3']
我有一个很大的数据集,而 .loc[] 花费的时间太长,所以我找到了一种矢量化的方法来完成它。回想一下,您可以将列设置为逻辑运算符,这样就可以了:
file['Flag'] = (file['Claim_Amount'] > 0)
这给出了一个布尔值,这是我想要的,但您可以将它乘以 1 得到一个整数。
我相信 Series.map() 非常易读且高效,例如:
df["c2"] = df["c1"].map(lambda x: 10 if x == 'Value' else x)
我喜欢它,因为如果条件逻辑变得更复杂,您可以将它移到一个函数中,然后只传入该函数而不是 lambda。
如果您需要将条件逻辑基于不止一列,您可以按照其他人的建议使用 DataFrame.apply()。
我需要根据 Pandas 数据框中另一列的值设置一列的值。这是逻辑:
if df['c1'] == 'Value':
df['c2'] = 10
else:
df['c2'] = df['c3']
我无法让它做我想做的事,即简单地创建一个具有新值的列(或更改现有列的值:任何一个都适合我)。
如果我尝试 运行 上面的代码,或者如果我将它写成一个函数并使用 apply 方法,我会得到以下结果:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
尝试:
df['c2'] = df['c1'].apply(lambda x: 10 if x == 'Value' else x)
一种方法是使用 .loc
的索引。
例子
由于没有示例数据框,我会在这里补一个:
import numpy as np
import pandas as pd
df = pd.DataFrame({'c1': list('abcdefg')})
df.loc[5, 'c1'] = 'Value'
>>> df
c1
0 a
1 b
2 c
3 d
4 e
5 Value
6 g
假设您想要创建一个新列 c2
,等同于 c1
,除了 c1
是 Value
,在这种情况下,您想将其分配给 10:
首先,您可以创建一个新列 c2
,并将其设置为等同于 c1
,使用以下两行之一(它们基本上做同样的事情):
df = df.assign(c2 = df['c1'])
# OR:
df['c2'] = df['c1']
然后,使用 .loc
找到 c1
等于 'Value'
的所有索引,并在这些索引处在 c2
中分配您想要的值:
df.loc[df['c1'] == 'Value', 'c2'] = 10
你最终得到这个:
>>> df
c1 c2
0 a a
1 b b
2 c c
3 d d
4 e e
5 Value 10
6 g g
如果正如您在问题中所建议的那样,有时您可能只想替换您已有的列中的值,而不是创建一个新列,那么只需跳过列创建,并执行以下操作:
df['c1'].loc[df['c1'] == 'Value'] = 10
# or:
df.loc[df['c1'] == 'Value', 'c1'] = 10
给你:
>>> df
c1
0 a
1 b
2 c
3 d
4 e
5 10
6 g
您可以使用 np.where()
根据指定条件设置值:
#df
c1 c2 c3
0 4 2 1
1 8 7 9
2 1 5 8
3 3 3 5
4 3 6 8
现在根据您的情况更改(或设置)第 ['c2']
列中的值。
df['c2'] = np.where(df.c1 == 8,'X', df.c3)
c1 c2 c3
0 4 1 1
1 8 X 9
2 1 8 8
3 3 5 5
4 3 8 8
我建议分两步进行:
# set fixed value to 'c2' where the condition is met
df.loc[df['c1'] == 'Value', 'c2'] = 10
# copy value from 'c3' to 'c2' where the condition is NOT met
df.loc[df['c1'] != 'Value', 'c2'] = df[df['c1'] != 'Value', 'c3']
您可以使用 pandas.DataFrame.mask
添加几乎任意数量的条件:
data = {'a': [1,2,3,4,5], 'b': [6,8,9,10,11]}
d = pd.DataFrame.from_dict(data, orient='columns')
c = {'c1': (2, 'Value1'), 'c2': (3, 'Value2'), 'c3': (5, d['b'])}
d['new'] = np.nan
for value in c.values():
d['new'].mask(d['a'] == value[0], value[1], inplace=True)
d['new'] = d['new'].fillna('Else')
d
输出:
a b new
0 1 6 Else
1 2 8 Value1
2 3 9 Value2
3 4 10 Else
4 5 11 11
如果您有 small/medium 数据框,请尝试 df.apply(),
df['c2'] = df.apply(lambda x: 10 if x['c1'] == 'Value' else x['c1'], axis = 1)
否则,如果你有一个大数据框,请遵循上面评论中提到的切片技术。
注意反转选择的波浪线。它使用 pandas 方法(即比 if
/else
更快)。
df.loc[(df['c1'] == 'Value'), 'c2'] = 10
df.loc[~(df['c1'] == 'Value'), 'c2'] = df['c3']
我有一个很大的数据集,而 .loc[] 花费的时间太长,所以我找到了一种矢量化的方法来完成它。回想一下,您可以将列设置为逻辑运算符,这样就可以了:
file['Flag'] = (file['Claim_Amount'] > 0)
这给出了一个布尔值,这是我想要的,但您可以将它乘以 1 得到一个整数。
我相信 Series.map() 非常易读且高效,例如:
df["c2"] = df["c1"].map(lambda x: 10 if x == 'Value' else x)
我喜欢它,因为如果条件逻辑变得更复杂,您可以将它移到一个函数中,然后只传入该函数而不是 lambda。
如果您需要将条件逻辑基于不止一列,您可以按照其他人的建议使用 DataFrame.apply()。