Python equivalent of the R interaction() function

Viewed 289

Is there a straightforward way to produce interactions between different variables in python? For example, in R, suppose I have 3 different factors to consider: a, b, and c, and I want to make a new variable that shows the particular combination of these three factors for a particular observation.

> a = c(1, 2, 2, 2, 3)
> b = c(2, 3, 3, 3, 2)
> c = c('m', 'm', 'f', 'f', 'f')
> interaction(a, b, c)
[1] 1.2.m 2.3.m 2.3.f 2.3.f 3.2.f
12 Levels: 1.2.f 2.2.f 3.2.f 1.3.f 2.3.f 3.3.f 1.2.m 2.2.m 3.2.m ... 3.3.m

I would like to be able to use this interaction concept to make a new column in a pandas dataframe. For example, suppose I have the dataframe:

df = pd.DataFrame({"a": [1, 2, 2, 2, 3]
  , 'b': [2, 3, 3, 3, 2]
  , 'c': ['m', 'm', 'f', 'f', 'f']})

I can use the following to make something along the lines of what I'm looking for:

df['d'] = df.a.astype(str) + '_' + df.b.astype(str) + '_' + df.c

Is there already a built in function or method that would accomplish this? I suppose the only difference would be that I would not have to explicitly type the factors beforehand.

2 Answers

Use Series.str.cat method with multiple Series:

df['d'] = df.a.astype(str).str.cat([df.b.astype(str), df.c], sep='.')
print (df)
   a  b  c      d
0  1  2  m  1.2.m
1  2  3  m  2.3.m
2  2  3  f  2.3.f
3  2  3  f  2.3.f
4  3  2  f  3.2.f

Or with DataFrame - selected b,c columns:

df['d'] = df.a.astype(str).str.cat(df[['b','c']].astype(str), sep='.')
print (df)
   a  b  c      d
0  1  2  m  1.2.m
1  2  3  m  2.3.m
2  2  3  f  2.3.f
3  2  3  f  2.3.f
4  3  2  f  3.2.f

For all columns to new column:

df['d'] = df.astype(str).agg('.'.join, axis=1)
#alternative
df['d'] = df.astype(str).apply('.'.join, axis=1)
print (df)
   a  b  c      d
0  1  2  m  1.2.m
1  2  3  m  2.3.m
2  2  3  f  2.3.f
3  2  3  f  2.3.f
4  3  2  f  3.2.f

Make everything a string, convert each row to a list, join the list elements:

df.astype(str).apply(list, axis=1).str.join(".")
#0    1.2.m
#1    2.3.m
#2    2.3.f
#3    2.3.f
#4    3.2.f

This approach is faster than yours but somewhat slower than anything proposed by @jezrael.

Related