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

时间:2018-03-07 21:01:02

标签: python pandas conditional

我需要根据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().

9 个答案:

答案 0 :(得分:30)

执行此操作的一种方法是使用.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,相当于c1c1Value之外,在这种情况下,您想把它分配到10:

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

df = df.assign(c2 = df['c1'])
# OR:
df['c2'] = df['c1']

然后,使用c1找到'Value'等于.loc的所有索引,并在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

给你:

>>> df
      c1
0      a
1      b
2      c
3      d
4      e
5     10
6      g

答案 1 :(得分:7)

尝试:

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

答案 2 :(得分:5)

您可以使用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  c3 c4
0   4   1  1
1   8   9  X
2   1   8  8
3   3   5  5
4   3   8  8

答案 3 :(得分:3)

请注意使选择反向的tilda。它使用熊猫方法(即比public class BookMemberConfig : IEntityTypeConfiguration<BookMember> { public void Configure(EntityTypeBuilder<BookMember> builder) { builder.HasKey(x => new { x.BookId, x.MemberId }); builder.HasOne(bookmember => bookmember.Book) .WithMany(b => b.MembersWhoHaveRead) .HasForeignKey(b => b.BookId); builder.HasOne(bookmember => bookmember.Member) .WithMany(m => m.BooksRead) .HasForeignKey(m => m.MemberId); } } / if更快)。

else

答案 4 :(得分:1)

我建议分两步完成:

# 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']

答案 5 :(得分:0)

您可以使用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

答案 6 :(得分:0)

如果您有中小型数据框,请尝试df.apply(),

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

否则,如果您的数据框很大,请遵循上述注释中提到的切片技术。

答案 7 :(得分:0)

我有一个很大的数据集,而.loc []花费的时间太长,所以我找到了一种矢量化的方法。回想一下,您可以将列设置为逻辑运算符,因此可以正常工作:

_render()

这提供了我想要的布尔值,但是您可以将其乘以1,以得到一个整数。

答案 8 :(得分:0)

我相信 Series.map() 的可读性和效率都很高,例如:

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

我喜欢它,因为如果条件逻辑变得更复杂,您可以将它移到一个函数中,然后只传入该函数而不是 lambda。

如果您需要基于多列的条件逻辑,您可以按照其他人的建议使用 DataFrame.apply()