Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparison of a Dataframe column values with a list

Consider this 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]})

This is the code to get values of column C, where it is the first row of each group (Column A):

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

So first will be: (100, 200, 300).

Now I want to add new column which it will be 1 if value of column C for row is in firsts otherwise it will be 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

I used this:

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

But the output is:

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

I appreciate if anyone explain why my solution is wrong and what is actual solution to this problem?

like image 481
Mehrdad Salimi Avatar asked May 27 '17 15:05

Mehrdad Salimi


2 Answers

You can use isin method:

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

The reason your approach fails is that python in operator check the index of a Series instead of the values, the same as how a dictionary works:

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

Modifying your method as follows works:

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
like image 89
Psidom Avatar answered Nov 10 '22 15:11

Psidom


TL;DR:

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

Another one-step method would be to use np.where() and 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)

We use the return from isin as the condition in np.where() to return either

  • 1 when True
  • 0 when False

and assign them to a new column in the same dataframe df['D'].

Note: np.where allows more complex conditions with bitwise operators and replacement cases, i.e. 'bypass' on False

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

like image 5
Friedrich Avatar answered Nov 10 '22 15:11

Friedrich