7

In pandas, how can I copy or move a row to the top of the Data Frame without creating a copy of the Data Frame?

For example, I managed to do almost what I want with the code below, but I have the impression that there might be a better way to accomplish this:

import pandas as pd

df = pd.DataFrame({'Probe':['Test1','Test2','Test3'], 'Sequence':['AATGCGT','TGCGTAA','ATGCATG']})

df

   Probe Sequence
0  Test1  AATGCGT
1  Test2  TGCGTAA
2  Test3  ATGCATG

df_shifted = df.shift(1)

df_shifted

   Probe Sequence
0    NaN      NaN
1  Test1  AATGCGT
2  Test2  TGCGTAA


df_shifted.ix[0] = df.ix[2]

df_shifted

   Probe Sequence
0  Test3  ATGCATG
1  Test1  AATGCGT
2  Test2  TGCGTAA
ropolo
  • 117
  • 1
  • 1
  • 8

3 Answers3

9

pandas.concat:

df = pd.concat([df.iloc[[n],:], df.drop(n, axis=0)], axis=0)
Asclepius
  • 57,944
  • 17
  • 167
  • 143
Kartik
  • 8,347
  • 39
  • 73
7

Try this. You don't need to make a copy of the dataframe.

df["new"] = range(1,len(df)+1)

   Probe Sequence  new
0  Test1  AATGCGT    1
1  Test2  TGCGTAA    2
2  Test3  ATGCATG    3


df.ix[2,'new'] = 0
df.sort_values("new").drop('new', axis=1)

   Probe Sequence
2  Test3  ATGCATG
0  Test1  AATGCGT
1  Test2  TGCGTAA

Basically, since you can't insert the row into the index at 0, create a column so you can.

If you want the index ordered, use this:

df.sort_values("new").reset_index(drop='True').drop('new', axis=1)

   Probe Sequence
0  Test3  ATGCATG
1  Test1  AATGCGT
2  Test2  TGCGTAA

Edit: df.ix is deprecated. Here's the same method with .loc.

df["new"] = range(1,len(df)+1)
df.loc[df.index==2, 'new'] = 0
df.sort_values("new").drop('new', axis=1)
semblable
  • 773
  • 1
  • 8
  • 26
Merlin
  • 24,552
  • 41
  • 131
  • 206
  • Thanks for your answer, @Merlin. Your answer works and it is applicable to rows with index n. I prefer Kartik's approach since I prefer not to create a new column. – ropolo Aug 17 '16 at 18:56
  • 1
    @ropolo, Kartiks method exactly what you said do didn't want to do that is "without creating a copy of the Data Frame" – Merlin Aug 17 '16 at 19:09
  • @ropolo Replace 2 with 'n' – Merlin Aug 17 '16 at 19:13
  • That is a good point, @Merlin. The `pandas` [docs](http://pandas.pydata.org/pandas-docs/stable/merging.html) say that `pd.concat` makes a full copy of the data. I wasn't aware of that. I also read in the docs that one can set `copy=False` in `pd.concat`. In the case of `pd.merge`, it seems that `copy=False` "may improve performance / memory". That being said, I like your approach, and since it doesn't create a copy, I will accept it. – ropolo Aug 17 '16 at 21:19
  • By the way, @Merlin, would you mind providing some feedback on my own answer? Is it more expensive to add a row of NaN like in my answer, or to create a new column like in yours? – ropolo Aug 17 '16 at 21:23
0

Okay, I think I came up with a solution. By all means, please feel free to add your own answer if you think yours is better:

import numpy as np

df.ix[3] = np.nan

df

   Probe Sequence
0  Test1  AATGCGT
1  Test2  TGCGTAA
2  Test3  ATGCATG
3    NaN      NaN

df = df.shift(1)

   Probe Sequence
0    NaN      NaN
1  Test1  AATGCGT
2  Test2  TGCGTAA
3  Test3  ATGCATG

df.ix[0] = df.ix[2]

df

   Probe Sequence
0  Test3  ATGCATG
1  Test1  AATGCGT
2  Test2  TGCGTAA
3  Test3  ATGCATG
ropolo
  • 117
  • 1
  • 1
  • 8