157

I currently have a dataframe that looks like this:

           Unnamed: 1    Unnamed: 2   Unnamed: 3  Unnamed: 4
0   Sample Number  Group Number  Sample Name  Group Name
1             1.0           1.0          s_1         g_1
2             2.0           1.0          s_2         g_1
3             3.0           1.0          s_3         g_1
4             4.0           2.0          s_4         g_2

I'm looking for a way to delete the header row and make the first row the new header row, so the new dataframe would look like this:

    Sample Number  Group Number  Sample Name  Group Name
0             1.0           1.0          s_1         g_1
1             2.0           1.0          s_2         g_1
2             3.0           1.0          s_3         g_1
3             4.0           2.0          s_4         g_2

I've tried stuff along the lines of if 'Unnamed' in df.columns: then make the dataframe without the header df.to_csv(newformat,header=False,index=False) but I don't seem to be getting anywhere.

abhi
  • 1,712
  • 1
  • 19
  • 35
Jeremy G
  • 1,799
  • 2
  • 11
  • 14

10 Answers10

268
new_header = df.iloc[0] #grab the first row for the header
df = df[1:] #take the data less the header row
df.columns = new_header #set the header row as the df header
Simon
  • 19,130
  • 24
  • 140
  • 209
rgalbo
  • 3,495
  • 1
  • 18
  • 27
  • When I do this, the 0 index is also becoming a part of the header. Is there a way to remove the 0 index from my header row? – Pete Mar 25 '22 at 12:14
  • @Pete What is the output that you get from `df.columns`? – rgalbo Mar 31 '22 at 17:21
75

The dataframe can be changed by just doing

df.columns = df.iloc[0]
df = df[1:]

Then

df.to_csv(path, index=False) 

Should do the trick.

Asclepius
  • 49,954
  • 14
  • 144
  • 128
JoeCondron
  • 7,936
  • 2
  • 24
  • 27
58

If you want a one-liner, you can do:

df.rename(columns=df.iloc[0]).drop(df.index[0])
ostrokach
  • 14,836
  • 7
  • 69
  • 87
  • 1
    Make it `df.rename(columns=df.iloc[0]).drop(df.index[0]).reset_index(drop=True)` if you don't want your index to be missing something. – z33k Nov 02 '21 at 12:13
  • did work for me after making it a two-liner ' df.rename(columns=df.iloc[0, :], inplace=True) df.drop(df.index[0], inplace=True) – Marc Steffen Nov 16 '21 at 22:32
12

Another one-liner using Python swapping:

df, df.columns = df[1:] , df.iloc[0]

This won't reset the index

Although, the opposite won't work as expected df.columns, df = df.iloc[0], df[1:]

ijoel92
  • 139
  • 1
  • 4
8

@ostrokach answer is best. Most likely you would want to keep that throughout any references to the dataframe, thus would benefit from inplace = True.
df.rename(columns=df.iloc[0], inplace = True) df.drop([0], inplace = True)

GoPackGo
  • 189
  • 3
  • 7
6

Here's a simple trick that defines column indices "in place". Because set_index sets row indices in place, we can do the same thing for columns by transposing the data frame, setting the index, and transposing it back:

df = df.T.set_index(0).T

Note you may have to change the 0 in set_index(0) if your rows have a different index already.

Alex P. Miller
  • 1,928
  • 20
  • 19
2

Alternatively, we can do this when reading a file with pandas.

This case we can use,

pd.read_csv('file_path',skiprows=1)

When reading the file this will skip the first row and will set the column as the second row of the file.

Ransaka Ravihara
  • 1,471
  • 1
  • 10
  • 26
  • This does not solve the problem. The values in the second row are not supposed to be the header values. In fact, this is basically the reverse of what the solution should be. If skiprows=-1 would cause the first row to be used as the header, that would be the solution. The accepted solution accomplishes the goal. – Anthony Sep 29 '21 at 14:01
1

--another way to do this


df.columns = df.iloc[0]
df = df.reindex(df.index.drop(0)).reset_index(drop=True)
df.columns.name = None

    Sample Number  Group Number  Sample Name  Group Name
0             1.0           1.0          s_1         g_1
1             2.0           1.0          s_2         g_1
2             3.0           1.0          s_3         g_1
3             4.0           2.0          s_4         g_2

If you like it hit up arrow. Thanks

rra
  • 655
  • 4
  • 14
0
header = table_df.iloc[0]
table_df.drop([0], axis =0, inplace=True)
table_df.reset_index(drop=True)
table_df.columns = header
table_df
-3

The best practice and Best OneLiner:

df.to_csv(newformat,header=1)

Notice the header value:

Header refer to the Row number(s) to use as the column names. Make no mistake, the row number is not the df but from the excel file(0 is the first row, 1 is the second and so on).

This way, you will get the column name you want and won't have to write additional codes or create new df.

Good thing is, it drops the replaced row.

yanger rai
  • 37
  • 7
  • 1
    This just outputs CSV though, it doesn't change the dataframe, right? – AMC Nov 06 '20 at 03:49
  • @AMC bit late in replying. To answer you question, Yes. It has no impact on dataframe. – yanger rai Feb 22 '21 at 16:29
  • So then this answer does not apply to the question and the one-liner doesn't solve the problem. The point isn't to generate a CSV; it's to replace the dataframe's headers with the values in the first row. – Anthony Sep 29 '21 at 13:54
  • It replace the dataframe headers on pandas. The code itself is "df.", df is your dataframe reading the data from your csv file – yanger rai Jan 27 '22 at 13:48