Dataframe列值与列表的比较

时间:2017-05-27 15:04:50

标签: python pandas dataframe

考虑这个数据帧:

df = pd.DataFrame({'A': [1, 1, 2, 2, 3, 3],
 'B': [10, 15, 20, 25, 30,35],
 'C': [100, 150, 200, 250, 300, 350]},)


A   B   C
1   10  100
1   15  150
2   20  200
2   25  250
3   30  300
3   35  350

我用它来获取每组第一行的C列值:

firsts = df.groupby('A').first()['C']

首先是:(100, 200, 300)

现在我要添加新列,它将是' 1'如果行的列C的值在firsts中,否则它将为' 0'。

   A    B   C   D
   1    10  100 1
   1    15  150 0
   2    20  200 1
   2    25  250 0
   3    30  300 1
   3    35  350 0

我用过这个:

df['D'] = df['C'].apply(lambda x: 1 if x in firsts else 0)

但输出是:

   A    B   C   D
   1    10  100 0
   1    15  150 0
   2    20  200 0
   2    25  250 0
   3    30  300 0
   3    35  350 0

我很感激,如果有人解释为什么我的解决方案是错误的,这个问题的实际解决方案是什么。

4 个答案:

答案 0 :(得分:7)

您可以使用isin方法:

df['D'] = df.C.isin(firsts).astype(int)

df
#   A   B   C   D
#0  1   10  100 1
#1  1   15  150 0
#2  2   20  200 1
#3  2   25  250 0
#4  3   30  300 1
#5  3   35  350 0

您的方法失败的原因是python in运算符检查Series的索引而不是值,与字典的工作方式相同:

firsts
#A
#1    100
#2    200
#3    300
#Name: C, dtype: int64

1 in firsts
# True

100 in firsts
# False

2 in firsts
# True

200 in firsts
# False

按如下方式修改方法:

firstSet = set(firsts)
df['C'].apply(lambda x: 1 if x in firstSet else 0)

#0    1
#1    0
#2    1
#3    0
#4    1
#5    0
#Name: C, dtype: int64

答案 1 :(得分:1)

您也可以使用.transform('first')

一步完成
In [280]: df['D'] = df.groupby('A')['C'].transform('first').eq(df['C']).astype(np.int8)

In [281]: df
Out[281]:
   A   B    C  D
0  1  10  100  1
1  1  15  150  0
2  2  20  200  1
3  2  25  250  0
4  3  30  300  1
5  3  35  350  0

说明: GroupBy.transform('func')向我们返回一个与原始DF长度相同的向量,并应用了func

In [14]: df.groupby('A')['C'].transform('first')
Out[14]:
0    100
1    100
2    200
3    200
4    300
5    300
Name: C, dtype: int64

In [15]: df.groupby('A')['C'].transform('max')
Out[15]:
0    150
1    150
2    250
3    250
4    350
5    350
Name: C, dtype: int64

In [16]: df.groupby('A')['C'].transform('min')
Out[16]:
0    100
1    100
2    200
3    200
4    300
5    300
Name: C, dtype: int64

In [17]: df.groupby('A')['C'].transform('mean')
Out[17]:
0    125
1    125
2    225
3    225
4    325
5    325
Name: C, dtype: int64

In [18]: df.groupby('A')['C'].transform('sum')
Out[18]:
0    250
1    250
2    450
3    450
4    650
5    650
Name: C, dtype: int64

答案 2 :(得分:1)

<强> TL; DR:

df['newColumn'] = np.where((df.compareColumn.isin(yourlist)), TrueValue, FalseValue)

另一个单步方法是使用np.where()isin

import pandas as pd
import numpy as np

df = pd.DataFrame({'A': [1, 1, 2, 2, 3, 3],
                   'B': [10, 15, 20, 25, 30,35],
                   'C': [100, 150, 200, 250, 300, 350]})

df['D'] = np.where((df.B.isin(firsts)), 1, 0)

我们使用isin的返回作为np.where()中的条件返回

    1 时,
  • True0
  • 时,
  • False

并将它们分配到同一数据框df['D']中的新列。

注意: np.where允许使用bitwise运算符和替换案例的更复杂条件,即False上的“绕过”

df['col1'] = np.where(((df['col1'] == df['col2']) &
                       (~df['col1'].str.startswith('r'))),
                       'replace', df['col1'])

答案 3 :(得分:-1)

firsts是pandas系列,因此当我们使用in搜索值时,它将在索引列表中搜索该值以解决此问题,我们可以将firsts转换为list或array

%timeit df['D'] = df['C'].apply(lambda x: 1 if x in firsts.values else 0)

每个循环314 µs±17.3 µs(平均±标准偏差,共运行7次,每个循环1000次)

%timeit df['D'] = df['C'].apply(lambda x: 1 if x in list(firsts) else 0)

每个循环301 µs±11.2 µs(平均±标准偏差,共运行7次,每个循环1000次)

%timeit df['D'] = list(map(lambda x: 1 if x in list(firsts) else 0,list(df['C'])))

每个循环27.6 µs±1.02 µs(平均±标准偏差,共运行7次,每个10000个循环)