Reputation: 3919
I have a Pandas DataFrame that contains IDs with associated values and for each value and I want to create a new column that has a value that ranges around the initial value by a determinable amount. My initial data looks like this;
iD Value
AAAA 10
AAAA 15
AAAA 5
BBBB 10
BBBB 6
BBBB 11
CCCC 8
CCCC 16
CCCC 14
The code I have so far is the following, where the range is set to +/- 1;
def add_range(lower, higher, oldval):
for i in range(lower,higher):
print i
newval = oldval + i
return newel
lower = -1
higher = 1
MSet['NewVal'] = MSet.apply(lambda row: add_range(row['Ords'],lower,higher), axis =1)
What I would like to get to is;
iD Value NewVal
AAAA 10 9
AAAA 10 10
AAAA 10 11
AAAA 15 14
AAAA 15 15
AAAA 15 16
AAAA 5 4
AAAA 5 5
AAAA 5 6
BBBB 10 9
BBBB 10 10
BBBB 10 11
BBBB 6 5
BBBB 6 6
BBBB 6 7
BBBB 11 10
BBBB 11 11
BBBB 11 12
CCCC 8 7
CCCC 8 8
CCCC 8 9
CCCC 16 14
CCCC 16 15
CCCC 16 16
CCCC 14 13
CCCC 14 14
CCCC 14 15
Any tips or suggestions would be massively appreciated.
Thanks!
Upvotes: 1
Views: 1002
Reputation: 323226
pandas.repeat
, then using groupby
, and unlist
df1=df.loc[df.index.repeat(3)]
import operator
df1.groupby(['iD','Value'],as_index=False).apply(lambda x :list(map(operator.sub, x['Value'], [1,0,-1]))).\
apply(pd.Series).stack().reset_index().\
drop('level_2',1).rename(columns={0:'New'})
Out[253]:
iD Value New
0 AAAA 5 4
1 AAAA 5 5
2 AAAA 5 6
3 AAAA 10 9
4 AAAA 10 10
5 AAAA 10 11
6 AAAA 15 14
7 AAAA 15 15
8 AAAA 15 16
9 BBBB 6 5
10 BBBB 6 6
11 BBBB 6 7
12 BBBB 10 9
13 BBBB 10 10
14 BBBB 10 11
15 BBBB 11 10
16 BBBB 11 11
17 BBBB 11 12
18 CCCC 8 7
19 CCCC 8 8
20 CCCC 8 9
21 CCCC 14 13
22 CCCC 14 14
23 CCCC 14 15
24 CCCC 16 15
25 CCCC 16 16
26 CCCC 16 17
Upvotes: 1
Reputation: 294258
Option 1
Simpler with loc
df.loc[df.index.repeat(3)].assign(
NewVal=(df.Value.values[:, None] + [-1, 0, 1]).ravel())
Option 2
Or rebuild the entire dataframe
i = df.iD.values
v = df.Value.values
pd.DataFrame(
np.column_stack([
i.repeat(3),
v.repeat(3),
(v[:, None] + [-1, 0, 1]).ravel()
]), columns=['iD', 'Value', 'NewVal']
)
Both options make use of adding [-1, 0, 1]
to the values using numpy broadcasting and then ravel
iD Value NewVal
0 AAAA 10 9
1 AAAA 10 10
2 AAAA 10 11
3 AAAA 15 14
4 AAAA 15 15
5 AAAA 15 16
6 AAAA 5 4
7 AAAA 5 5
8 AAAA 5 6
9 BBBB 10 9
10 BBBB 10 10
11 BBBB 10 11
12 BBBB 6 5
13 BBBB 6 6
14 BBBB 6 7
15 BBBB 11 10
16 BBBB 11 11
17 BBBB 11 12
18 CCCC 8 7
19 CCCC 8 8
20 CCCC 8 9
21 CCCC 16 15
22 CCCC 16 16
23 CCCC 16 17
24 CCCC 14 13
25 CCCC 14 14
26 CCCC 14 15
Upvotes: 3