11

I have the following pandas Dataframe:

import pandas as pd
data = {'one' : pd.Series([1.], index=['a']), 'two' : pd.Series([1., 2.], index=['a', 'b']), 'three' : pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(data)
df = df[["one", "two", "three"]]


   one  two  three
a  1.0  1.0    1.0
b  NaN  2.0    2.0
c  NaN  NaN    3.0
d  NaN  NaN    4.0

I know how to shift elements by column upwards/downwards, e.g.

df.two = df.two.shift(-1)

   one  two  three
a  1.0  2.0    1.0
b  NaN  NaN    2.0
c  NaN  NaN    3.0
d  NaN  NaN    4.0

However, I would like to shift all elements in row a over two columns and all elements in row b over one column. The final data frame would look like this:

   one  two  three
a  NaN  NaN    1.0
b  NaN  NaN    2.0
c  NaN  NaN    3.0
d  NaN  NaN    4.0

How does one do this in pandas?

1
  • 1
    We don't need to transpose the DF, just choose the axis parameter in the shift. Look my answer! Commented Feb 5, 2021 at 12:01

2 Answers 2

7

You can transpose the initial DF so that you have a way to access the row labels as column names inorder to perform the shift operation.

Shift the contents of the respective columns downward by those amounts and re-transpose it back to get the desired result.

df_t = df.T
df_t.assign(a=df_t['a'].shift(2), b=df_t['b'].shift(1)).T

enter image description here

Sign up to request clarification or add additional context in comments.

6 Comments

Nice solution! I think we can even improve it a bit - .shift() accepts axis parameter: df.assign(one=df[['one']].shift(2, axis=1), two=df[['two']].shift(1, axis=1))
Yeah, that seems to be a good suggestion. But then, won't the amount with which it gets shifted have no influence on the outcome as we're merely selecting a single columned DF and performing shift across columns?
Try for this case - df = pd.DataFrame(np.arange(12).reshape(4,3), list('abcd'), ['one','two','three']), you'll understand what I mean. Moreover, the OP wants just the first two rows to be modifed :-)
yep, i got it now. Thank you for the explanation! I can't upvote your answer the second time though ;-)
This is a new question, but I'm curious: Instead of just a=df_t['a'].shift(2), b=df_t['b'].shift(1), what if there were multiple columns in need of shifting? Like columns a though z in need of shifting 2, columns 20 through 100 in need of shifting 5, etc.?
|
3

IMHO, this is a more pythonic way:

df.loc['a'] = df.loc['a'].shift(periods=2,axis=0)

Note in this case .loc returns a Series, so axis=0 is optional.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.