Pandas/Python:根据另一列中的值设置一列的值

NLR*_*NLR 31 python conditional pandas

我需要根据Pandas数据帧中另一列的值设置一列的值.这是逻辑:

if df['c1'] == 'Value':
    df['c2'] = 10
else:
    df['c2'] = df['c3']
Run Code Online (Sandbox Code Playgroud)

我无法做到这一点,我只想创建一个具有新值的列(或更改现有列的值:任何一个适合我).

如果我尝试运行上面的代码或者如果我将其作为函数编写并使用apply方法,我会得到以下内容:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Run Code Online (Sandbox Code Playgroud)

sac*_*cuL 45

一种方法是使用索引.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
Run Code Online (Sandbox Code Playgroud)

假设你想创建一个新的列 c2,相当于c1除非c1Value,在这种情况下,你想将其分配到10:

首先,您可以使用以下两行之一创建一个新列c2,并将其设置为等效的c1(它们基本上做同样的事情):

df = df.assign(c2 = df['c1'])
# OR:
df['c2'] = df['c1']
Run Code Online (Sandbox Code Playgroud)

然后,找到所有c1等于'Value'使用的索引.loc,并c2在这些索引处分配所需的值:

df.loc[df['c1'] == 'Value', 'c2'] = 10
Run Code Online (Sandbox Code Playgroud)

你最终得到了这个:

>>> df
      c1  c2
0      a   a
1      b   b
2      c   c
3      d   d
4      e   e
5  Value  10
6      g   g
Run Code Online (Sandbox Code Playgroud)

如果,正如您在问题中所建议的那样,您有时可能只想替换已有列中的值,而不是创建新列,那么只需跳过列创建,然后执行以下操作:

df['c1'].loc[df['c1'] == 'Value'] = 10
# or:
df.loc[df['c1'] == 'Value', 'c1'] = 10
Run Code Online (Sandbox Code Playgroud)

给你:

>>> df
      c1
0      a
1      b
2      c
3      d
4      e
5     10
6      g
Run Code Online (Sandbox Code Playgroud)

  • 第二种解决方案为我钉上了钉子。我没有意识到您可以像SQL中的WHERE语句一样使用.loc。说得通。谢谢! (2认同)

DJK*_*DJK 13

您可以用来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
Run Code Online (Sandbox Code Playgroud)

现在['c2']根据您的条件更改列中的值(或设置)。

df['c2'] = np.where(df.c1 == 8,'X',df.c3)

  c1  c3 c4
0   4   1  1
1   8   9  X
2   1   8  8
3   3   5  5
4   3   8  8
Run Code Online (Sandbox Code Playgroud)

  • @mLstudent33,使用“df['newColName'] = ...”,您使用列名称,而不是在数据框中创建新列,假设“newColName”尚不存在 (2认同)

小智 10

尝试:

df['c2'] = df['c1'].apply(lambda x: 10 if x == 'Value' else x)

  • 应该为df.apply(lambda x:如果x ['c1'] =='Value'则为10,否则x ['c3'],axis = 1)` (5认同)
  • 大型数据集可能存在性能问题。df.apply()较慢。 (3认同)

小智 8

请注意反转选择的 tilda。它使用熊猫方法(即比if/快else)。

df.loc[(df['c1'] == 'Value'), 'c2'] = 10
df.loc[~(df['c1'] == 'Value'), 'c2'] = df['c3']
Run Code Online (Sandbox Code Playgroud)


Ral*_*alf 7

我建议分两步进行:

# 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']
Run Code Online (Sandbox Code Playgroud)


nim*_*ous 5

您可以根据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
Run Code Online (Sandbox Code Playgroud)

输出:

    a   b   new
0   1   6   Else
1   2   8   Value1
2   3   9   Value2
3   4   10  Else
4   5   11  11
Run Code Online (Sandbox Code Playgroud)