Move column by name to front of table in pandas
Question:
Here is my df:
Net Upper Lower Mid Zsore
Answer option
More than once a day 0% 0.22% -0.12% 2 65
Once a day 0% 0.32% -0.19% 3 45
Several times a week 2% 2.45% 1.10% 4 78
Once a week 1% 1.63% -0.40% 6 65
How can I move a column by name ("Mid"
) to the front of the table, index 0. This is what the result should look like:
Mid Upper Lower Net Zsore
Answer option
More than once a day 2 0.22% -0.12% 0% 65
Once a day 3 0.32% -0.19% 0% 45
Several times a week 4 2.45% 1.10% 2% 78
Once a week 6 1.63% -0.40% 1% 65
My current code moves the column by index using df.columns.tolist()
but I’d like to shift it by name.
Answers:
We can use loc
to reorder by passing a list:
In [27]:
# get a list of columns
cols = list(df)
# move the column to head of list using index, pop and insert
cols.insert(0, cols.pop(cols.index('Mid')))
cols
Out[27]:
['Mid', 'Net', 'Upper', 'Lower', 'Zsore']
In [28]:
# use ix to reorder
df = df.loc[:, cols]
df
Out[28]:
Mid Net Upper Lower Zsore
Answer_option
More_than_once_a_day 2 0% 0.22% -0.12% 65
Once_a_day 3 0% 0.32% -0.19% 45
Several_times_a_week 4 2% 2.45% 1.10% 78
Once_a_week 6 1% 1.63% -0.40% 65
Another method is to take a reference to the column and reinsert it at the front:
In [39]:
mid = df['Mid']
df.drop(labels=['Mid'], axis=1,inplace = True)
df.insert(0, 'Mid', mid)
df
Out[39]:
Mid Net Upper Lower Zsore
Answer_option
More_than_once_a_day 2 0% 0.22% -0.12% 65
Once_a_day 3 0% 0.32% -0.19% 45
Several_times_a_week 4 2% 2.45% 1.10% 78
Once_a_week 6 1% 1.63% -0.40% 65
You can, with very early versions of Pandas, also use ix
to achieve the same results:
df = df.ix[:, cols]
But ix
was deprecated from pandas 0.20.0
onwards and was discontinued as of Pandas 1.0.
You can use the df.reindex() function in pandas.
df is
Net Upper Lower Mid Zsore
Answer option
More than once a day 0% 0.22% -0.12% 2 65
Once a day 0% 0.32% -0.19% 3 45
Several times a week 2% 2.45% 1.10% 4 78
Once a week 1% 1.63% -0.40% 6 65
define an list of column names
cols = df.columns.tolist()
cols
Out[13]: ['Net', 'Upper', 'Lower', 'Mid', 'Zsore']
move the column name to wherever you want
cols.insert(0, cols.pop(cols.index('Mid')))
cols
Out[16]: ['Mid', 'Net', 'Upper', 'Lower', 'Zsore']
then use df.reindex()
function to reorder
df = df.reindex(columns= cols)
out put is: df
Mid Upper Lower Net Zsore
Answer option
More than once a day 2 0.22% -0.12% 0% 65
Once a day 3 0.32% -0.19% 0% 45
Several times a week 4 2.45% 1.10% 2% 78
Once a week 6 1.63% -0.40% 1% 65
I didn’t like how I had to explicitly specify all the other column in the other solutions.
cfg_col_sel = ['Mid', 'Zscore']
cfg_col_sel = cfg_col_sel+[s for s in df.columns if not s in cfg_col_sel]
df = df[cfg_col_sel]
This is another way of doing it but less flexible
df = df.set_index('Mid').reset_index()
Here is a generic set of code that I frequently use to rearrange the position of columns. You may find it useful.
cols = df.columns.tolist()
n = int(cols.index('Mid'))
cols = [cols[n]] + cols[:n] + cols[n+1:]
df = df[cols]
Maybe I’m missing something, but a lot of these answers seem overly complicated. You should be able to just set the columns within a single list:
Column to the front:
df = df[ ['Mid'] + [ col for col in df.columns if col != 'Mid' ] ]
Or if instead, you want to move it to the back:
df = df[ [ col for col in df.columns if col != 'Mid' ] + ['Mid'] ]
Or if you wanted to move more than one column:
cols_to_move = ['Mid', 'Zsore']
df = df[ cols_to_move + [ col for col in df.columns if col not in cols_to_move ] ]
To reorder the rows of a DataFrame just use a list as follows.
df = df[['Mid', 'Net', 'Upper', 'Lower', 'Zsore']]
This makes it very obvious what was done when reading the code later. Also use:
df.columns
Out[1]: Index(['Net', 'Upper', 'Lower', 'Mid', 'Zsore'], dtype='object')
Then cut and paste to reorder.
For a DataFrame with many columns, store the list of columns in a variable and pop the desired column to the front of the list. Here is an example:
cols = [str(col_name) for col_name in range(1001)]
data = np.random.rand(10,1001)
df = pd.DataFrame(data=data, columns=cols)
mv_col = cols.pop(cols.index('77'))
df = df[[mv_col] + cols]
Now df.columns
has.
Index(['77', '0', '1', '2', '3', '4', '5', '6', '7', '8',
...
'991', '992', '993', '994', '995', '996', '997', '998', '999', '1000'],
dtype='object', length=1001)
I prefer this solution:
col = df.pop("Mid")
df.insert(0, col.name, col)
It’s simpler to read and faster than other suggested answers.
def move_column_inplace(df, col, pos):
col = df.pop(col)
df.insert(pos, col.name, col)
Performance assessment:
For this test, the currently last column is moved to the front in each repetition. In-place methods generally perform better. While citynorman’s solution can be made in-place, Ed Chum’s method based on .loc
and sachinnm’s method based on reindex
cannot.
While other methods are generic, citynorman’s solution is limited to pos=0
. I didn’t observe any performance difference between df.loc[cols]
and df[cols]
, which is why I didn’t include some other suggestions.
Original system (2019): Python 3.6.8 and pandas 0.24.2 on a MacBook Pro (Mid 2015).
Current system (2022): Python 3.10.5 and pandas 1.4.3 on a MacBook Pro (2021, Apple M1).
import numpy as np
import pandas as pd
n_cols = 11
df = pd.DataFrame(np.random.randn(200000, n_cols),
columns=range(n_cols))
def move_column_inplace(df, col, pos):
col = df.pop(col)
df.insert(pos, col.name, col)
def move_to_front_normanius_inplace(df, col):
move_column_inplace(df, col, 0)
return df
def move_to_front_chum(df, col):
cols = list(df)
cols.insert(0, cols.pop(cols.index(col)))
return df.loc[:, cols]
def move_to_front_chum_inplace(df, col):
col = df[col]
df.drop(col.name, axis=1, inplace=True)
df.insert(0, col.name, col)
return df
def move_to_front_elpastor(df, col):
cols = [col] + [ c for c in df.columns if c!=col ]
return df[cols] # or df.loc[cols]
def move_to_front_sachinmm(df, col):
cols = df.columns.tolist()
cols.insert(0, cols.pop(cols.index(col)))
df = df.reindex(columns=cols, copy=False)
return df
def move_to_front_citynorman_inplace(df, col):
# This approach exploits that reset_index() moves the index
# at the first position of the data frame.
df.set_index(col, inplace=True)
df.reset_index(inplace=True)
return df
def test(method, df):
col = np.random.randint(0, n_cols)
method(df, col)
col = np.random.randint(0, n_cols)
ret_mine = move_to_front_normanius_inplace(df.copy(), col)
ret_chum1 = move_to_front_chum(df.copy(), col)
ret_chum2 = move_to_front_chum_inplace(df.copy(), col)
ret_elpas = move_to_front_elpastor(df.copy(), col)
ret_sach = move_to_front_sachinmm(df.copy(), col)
ret_city = move_to_front_citynorman_inplace(df.copy(), col)
# Assert equivalence of solutions.
assert(ret_mine.equals(ret_chum1))
assert(ret_mine.equals(ret_chum2))
assert(ret_mine.equals(ret_elpas))
assert(ret_mine.equals(ret_sach))
assert(ret_mine.equals(ret_city))
Results:
# For n_cols = 11:
%timeit test(move_to_front_normanius_inplace, df)
# 137 µs ± 692 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 177 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_sachinmm, df)
# 821 µs ± 11.8 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_chum, df)
# 926 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_elpastor, df)
# 901 µs ± 6.44 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 3.25 ms ± 32.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# For n_cols = 31:
%timeit test(move_to_front_normanius_inplace, df)
# 188 µs ± 3.46 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 214 µs ± 649 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_sachinmm, df)
# 5.17 ms ± 68.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum, df)
# 5.52 ms ± 82.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_elpastor, df)
# 5.48 ms ± 198 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 14.7 ms ± 317 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Above are the updated values for a rerun in 2022. The rankings have remained stable over the past years for different systems, although the absolute numbers have decreased by factors between 2 and 10, from which citynorman’s solution and my solution (normanius) have benefited the most.
Here is a very simple answer to this.
Don’t forget the two (()) ‘brackets’ around columns names.Otherwise, it’ll give you an error.
# here you can add below line and it should work
df = df[list(('Mid','Upper', 'Lower', 'Net','Zsore'))]
df
Mid Upper Lower Net Zsore
Answer option
More than once a day 2 0.22% -0.12% 0% 65
Once a day 3 0.32% -0.19% 0% 45
Several times a week 4 2.45% 1.10% 2% 78
Once a week 6 1.63% -0.40% 1% 65
The most simplist thing you can try is:
df=df[[ 'Mid', 'Upper', 'Lower', 'Net' , 'Zsore']]
df.set_index('Mid').reset_index()
seems to be a pretty easy way about this.
If you want to move to another place and reassign the name as well, you can do as the following:
df.insert(0, 'new col name', col)
df.pop("Mid")
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.insert.html
If you want to move a column to the front of the dataframe, you can use
use set_index()
.
df.set_index(df.pop('column_name'), inplace=True)
df.reset_index(inplace=True)
You first need to set the column you want to bring to the front as the index of the dataframe (and we do a pop
in order to drop the column from the original dataframe before setting it as the index in order to avoid name collision in the next action) and finally call reset_index()
to make the old index the first column of the dataframe.
For more details see How to change the order of dataframe columns in pandas.
You can use movecolumn package in Python to move columns:
pip install movecolumn
Then you can write your code as:
import movecolumn as mc
mc.MoveTo1(df,'mid')
Hope that helps.
P.S : The package can be found here. https://pypi.org/project/movecolumn/
Easy and quick solution::
For pandas >= 1.3 (Edited in 2022):
df.insert(0, 'mean', df.pop('mean'))
How about (for Pandas < 1.3, the original answer)
df.insert(0, 'mean', df['mean'])
You can use these methods.
Here you will "delete" the Mid column. If you use the method pop() will delete the column from the db but it will keep it in memory. That’s why I put a variable equal to the column that we are goind to "delete".
column_mid = df.pop("Mid")
After that, you can use the method insert() which will allow you to put the column Mid in whichever position that you indicate. In this case will be the position 0.
df.insert(0, "Mid", column_mid)
And that’s it. If you have any query, let me know.
Regards!
Octavio Velázquez
Here is my df:
Net Upper Lower Mid Zsore
Answer option
More than once a day 0% 0.22% -0.12% 2 65
Once a day 0% 0.32% -0.19% 3 45
Several times a week 2% 2.45% 1.10% 4 78
Once a week 1% 1.63% -0.40% 6 65
How can I move a column by name ("Mid"
) to the front of the table, index 0. This is what the result should look like:
Mid Upper Lower Net Zsore
Answer option
More than once a day 2 0.22% -0.12% 0% 65
Once a day 3 0.32% -0.19% 0% 45
Several times a week 4 2.45% 1.10% 2% 78
Once a week 6 1.63% -0.40% 1% 65
My current code moves the column by index using df.columns.tolist()
but I’d like to shift it by name.
We can use loc
to reorder by passing a list:
In [27]:
# get a list of columns
cols = list(df)
# move the column to head of list using index, pop and insert
cols.insert(0, cols.pop(cols.index('Mid')))
cols
Out[27]:
['Mid', 'Net', 'Upper', 'Lower', 'Zsore']
In [28]:
# use ix to reorder
df = df.loc[:, cols]
df
Out[28]:
Mid Net Upper Lower Zsore
Answer_option
More_than_once_a_day 2 0% 0.22% -0.12% 65
Once_a_day 3 0% 0.32% -0.19% 45
Several_times_a_week 4 2% 2.45% 1.10% 78
Once_a_week 6 1% 1.63% -0.40% 65
Another method is to take a reference to the column and reinsert it at the front:
In [39]:
mid = df['Mid']
df.drop(labels=['Mid'], axis=1,inplace = True)
df.insert(0, 'Mid', mid)
df
Out[39]:
Mid Net Upper Lower Zsore
Answer_option
More_than_once_a_day 2 0% 0.22% -0.12% 65
Once_a_day 3 0% 0.32% -0.19% 45
Several_times_a_week 4 2% 2.45% 1.10% 78
Once_a_week 6 1% 1.63% -0.40% 65
You can, with very early versions of Pandas, also use ix
to achieve the same results:
df = df.ix[:, cols]
But ix
was deprecated from pandas 0.20.0
onwards and was discontinued as of Pandas 1.0.
You can use the df.reindex() function in pandas.
df is
Net Upper Lower Mid Zsore
Answer option
More than once a day 0% 0.22% -0.12% 2 65
Once a day 0% 0.32% -0.19% 3 45
Several times a week 2% 2.45% 1.10% 4 78
Once a week 1% 1.63% -0.40% 6 65
define an list of column names
cols = df.columns.tolist()
cols
Out[13]: ['Net', 'Upper', 'Lower', 'Mid', 'Zsore']
move the column name to wherever you want
cols.insert(0, cols.pop(cols.index('Mid')))
cols
Out[16]: ['Mid', 'Net', 'Upper', 'Lower', 'Zsore']
then use df.reindex()
function to reorder
df = df.reindex(columns= cols)
out put is: df
Mid Upper Lower Net Zsore
Answer option
More than once a day 2 0.22% -0.12% 0% 65
Once a day 3 0.32% -0.19% 0% 45
Several times a week 4 2.45% 1.10% 2% 78
Once a week 6 1.63% -0.40% 1% 65
I didn’t like how I had to explicitly specify all the other column in the other solutions.
cfg_col_sel = ['Mid', 'Zscore']
cfg_col_sel = cfg_col_sel+[s for s in df.columns if not s in cfg_col_sel]
df = df[cfg_col_sel]
This is another way of doing it but less flexible
df = df.set_index('Mid').reset_index()
Here is a generic set of code that I frequently use to rearrange the position of columns. You may find it useful.
cols = df.columns.tolist()
n = int(cols.index('Mid'))
cols = [cols[n]] + cols[:n] + cols[n+1:]
df = df[cols]
Maybe I’m missing something, but a lot of these answers seem overly complicated. You should be able to just set the columns within a single list:
Column to the front:
df = df[ ['Mid'] + [ col for col in df.columns if col != 'Mid' ] ]
Or if instead, you want to move it to the back:
df = df[ [ col for col in df.columns if col != 'Mid' ] + ['Mid'] ]
Or if you wanted to move more than one column:
cols_to_move = ['Mid', 'Zsore']
df = df[ cols_to_move + [ col for col in df.columns if col not in cols_to_move ] ]
To reorder the rows of a DataFrame just use a list as follows.
df = df[['Mid', 'Net', 'Upper', 'Lower', 'Zsore']]
This makes it very obvious what was done when reading the code later. Also use:
df.columns
Out[1]: Index(['Net', 'Upper', 'Lower', 'Mid', 'Zsore'], dtype='object')
Then cut and paste to reorder.
For a DataFrame with many columns, store the list of columns in a variable and pop the desired column to the front of the list. Here is an example:
cols = [str(col_name) for col_name in range(1001)]
data = np.random.rand(10,1001)
df = pd.DataFrame(data=data, columns=cols)
mv_col = cols.pop(cols.index('77'))
df = df[[mv_col] + cols]
Now df.columns
has.
Index(['77', '0', '1', '2', '3', '4', '5', '6', '7', '8',
...
'991', '992', '993', '994', '995', '996', '997', '998', '999', '1000'],
dtype='object', length=1001)
I prefer this solution:
col = df.pop("Mid")
df.insert(0, col.name, col)
It’s simpler to read and faster than other suggested answers.
def move_column_inplace(df, col, pos):
col = df.pop(col)
df.insert(pos, col.name, col)
Performance assessment:
For this test, the currently last column is moved to the front in each repetition. In-place methods generally perform better. While citynorman’s solution can be made in-place, Ed Chum’s method based on .loc
and sachinnm’s method based on reindex
cannot.
While other methods are generic, citynorman’s solution is limited to pos=0
. I didn’t observe any performance difference between df.loc[cols]
and df[cols]
, which is why I didn’t include some other suggestions.
Original system (2019): Python 3.6.8 and pandas 0.24.2 on a MacBook Pro (Mid 2015).
Current system (2022): Python 3.10.5 and pandas 1.4.3 on a MacBook Pro (2021, Apple M1).
import numpy as np
import pandas as pd
n_cols = 11
df = pd.DataFrame(np.random.randn(200000, n_cols),
columns=range(n_cols))
def move_column_inplace(df, col, pos):
col = df.pop(col)
df.insert(pos, col.name, col)
def move_to_front_normanius_inplace(df, col):
move_column_inplace(df, col, 0)
return df
def move_to_front_chum(df, col):
cols = list(df)
cols.insert(0, cols.pop(cols.index(col)))
return df.loc[:, cols]
def move_to_front_chum_inplace(df, col):
col = df[col]
df.drop(col.name, axis=1, inplace=True)
df.insert(0, col.name, col)
return df
def move_to_front_elpastor(df, col):
cols = [col] + [ c for c in df.columns if c!=col ]
return df[cols] # or df.loc[cols]
def move_to_front_sachinmm(df, col):
cols = df.columns.tolist()
cols.insert(0, cols.pop(cols.index(col)))
df = df.reindex(columns=cols, copy=False)
return df
def move_to_front_citynorman_inplace(df, col):
# This approach exploits that reset_index() moves the index
# at the first position of the data frame.
df.set_index(col, inplace=True)
df.reset_index(inplace=True)
return df
def test(method, df):
col = np.random.randint(0, n_cols)
method(df, col)
col = np.random.randint(0, n_cols)
ret_mine = move_to_front_normanius_inplace(df.copy(), col)
ret_chum1 = move_to_front_chum(df.copy(), col)
ret_chum2 = move_to_front_chum_inplace(df.copy(), col)
ret_elpas = move_to_front_elpastor(df.copy(), col)
ret_sach = move_to_front_sachinmm(df.copy(), col)
ret_city = move_to_front_citynorman_inplace(df.copy(), col)
# Assert equivalence of solutions.
assert(ret_mine.equals(ret_chum1))
assert(ret_mine.equals(ret_chum2))
assert(ret_mine.equals(ret_elpas))
assert(ret_mine.equals(ret_sach))
assert(ret_mine.equals(ret_city))
Results:
# For n_cols = 11:
%timeit test(move_to_front_normanius_inplace, df)
# 137 µs ± 692 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 177 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_sachinmm, df)
# 821 µs ± 11.8 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_chum, df)
# 926 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_elpastor, df)
# 901 µs ± 6.44 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 3.25 ms ± 32.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# For n_cols = 31:
%timeit test(move_to_front_normanius_inplace, df)
# 188 µs ± 3.46 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 214 µs ± 649 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit test(move_to_front_sachinmm, df)
# 5.17 ms ± 68.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum, df)
# 5.52 ms ± 82.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_elpastor, df)
# 5.48 ms ± 198 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 14.7 ms ± 317 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Above are the updated values for a rerun in 2022. The rankings have remained stable over the past years for different systems, although the absolute numbers have decreased by factors between 2 and 10, from which citynorman’s solution and my solution (normanius) have benefited the most.
Here is a very simple answer to this.
Don’t forget the two (()) ‘brackets’ around columns names.Otherwise, it’ll give you an error.
# here you can add below line and it should work
df = df[list(('Mid','Upper', 'Lower', 'Net','Zsore'))]
df
Mid Upper Lower Net Zsore
Answer option
More than once a day 2 0.22% -0.12% 0% 65
Once a day 3 0.32% -0.19% 0% 45
Several times a week 4 2.45% 1.10% 2% 78
Once a week 6 1.63% -0.40% 1% 65
The most simplist thing you can try is:
df=df[[ 'Mid', 'Upper', 'Lower', 'Net' , 'Zsore']]
df.set_index('Mid').reset_index()
seems to be a pretty easy way about this.
If you want to move to another place and reassign the name as well, you can do as the following:
df.insert(0, 'new col name', col)
df.pop("Mid")
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.insert.html
If you want to move a column to the front of the dataframe, you can use
use set_index()
.
df.set_index(df.pop('column_name'), inplace=True)
df.reset_index(inplace=True)
You first need to set the column you want to bring to the front as the index of the dataframe (and we do a pop
in order to drop the column from the original dataframe before setting it as the index in order to avoid name collision in the next action) and finally call reset_index()
to make the old index the first column of the dataframe.
For more details see How to change the order of dataframe columns in pandas.
You can use movecolumn package in Python to move columns:
pip install movecolumn
Then you can write your code as:
import movecolumn as mc
mc.MoveTo1(df,'mid')
Hope that helps.
P.S : The package can be found here. https://pypi.org/project/movecolumn/
Easy and quick solution::
For pandas >= 1.3 (Edited in 2022):
df.insert(0, 'mean', df.pop('mean'))
How about (for Pandas < 1.3, the original answer)
df.insert(0, 'mean', df['mean'])
You can use these methods.
Here you will "delete" the Mid column. If you use the method pop() will delete the column from the db but it will keep it in memory. That’s why I put a variable equal to the column that we are goind to "delete".
column_mid = df.pop("Mid")
After that, you can use the method insert() which will allow you to put the column Mid in whichever position that you indicate. In this case will be the position 0.
df.insert(0, "Mid", column_mid)
And that’s it. If you have any query, let me know.
Regards!
Octavio Velázquez