Stack or concatenate dataframes

import seaborn as sns
import pandas as pd

df_wide = pd.read_csv('rates.csv', parse_dates=['Time'])
df_wide.index = df_wide['Time']
df_wide = df_wide.sort_index()
df_wide.head()
Time USD JPY BGN CZK DKK GBP CHF
Time
2023-10-20 2023-10-20 1.0591 158.80 1.9558 24.704 7.4620 0.87213 0.9442
2023-10-23 2023-10-23 1.0597 158.91 1.9558 24.645 7.4634 0.87153 0.9461
2023-10-24 2023-10-24 1.0632 159.26 1.9558 24.659 7.4648 0.87025 0.9501
2023-10-25 2023-10-25 1.0576 158.55 1.9558 24.693 7.4639 0.87240 0.9474
2023-10-26 2023-10-26 1.0540 158.48 1.9558 24.714 7.4632 0.87170 0.9466
df_USD_JPY_2023 = df_wide.loc['2023-12-14':'2023-12-20', ['USD', 'JPY']]
df_USD_JPY_2023
USD JPY
Time
2023-12-14 1.0919 154.80
2023-12-15 1.0946 155.15
2023-12-18 1.0918 155.95
2023-12-19 1.0962 158.20
2023-12-20 1.0944 157.12
df_CHF_2023_dec = df_wide.loc['2023-12-08':'2023-12-24', ['CHF']]
df_CHF_2023_dec
CHF
Time
2023-12-08 0.9438
2023-12-11 0.9478
2023-12-12 0.9443
2023-12-13 0.9452
2023-12-14 0.9490
2023-12-15 0.9488
2023-12-18 0.9480
2023-12-19 0.9470
2023-12-20 0.9460
2023-12-21 0.9432
2023-12-22 0.9417

Vertical stacking

pd.concat([df_USD_JPY_2023, df_CHF_2023_dec]) # vertical stacking
USD JPY CHF
Time
2023-12-14 1.0919 154.80 NaN
2023-12-15 1.0946 155.15 NaN
2023-12-18 1.0918 155.95 NaN
2023-12-19 1.0962 158.20 NaN
2023-12-20 1.0944 157.12 NaN
2023-12-08 NaN NaN 0.9438
2023-12-11 NaN NaN 0.9478
2023-12-12 NaN NaN 0.9443
2023-12-13 NaN NaN 0.9452
2023-12-14 NaN NaN 0.9490
2023-12-15 NaN NaN 0.9488
2023-12-18 NaN NaN 0.9480
2023-12-19 NaN NaN 0.9470
2023-12-20 NaN NaN 0.9460
2023-12-21 NaN NaN 0.9432
2023-12-22 NaN NaN 0.9417

Horizontal stacking (axis=1)

pd.concat([df_USD_JPY_2023, df_CHF_2023_dec], axis=1) # horizontal stacking
USD JPY CHF
Time
2023-12-08 NaN NaN 0.9438
2023-12-11 NaN NaN 0.9478
2023-12-12 NaN NaN 0.9443
2023-12-13 NaN NaN 0.9452
2023-12-14 1.0919 154.80 0.9490
2023-12-15 1.0946 155.15 0.9488
2023-12-18 1.0918 155.95 0.9480
2023-12-19 1.0962 158.20 0.9470
2023-12-20 1.0944 157.12 0.9460
2023-12-21 NaN NaN 0.9432
2023-12-22 NaN NaN 0.9417

Veritcal stacking with keys to create a MultiIndex for rows

pd.concat([df_USD_JPY_2023, df_CHF_2023_dec, df_USD_JPY_2023], keys=['first', 'second', 'first again'])
USD JPY CHF
Time
first 2023-12-14 1.0919 154.80 NaN
2023-12-15 1.0946 155.15 NaN
2023-12-18 1.0918 155.95 NaN
2023-12-19 1.0962 158.20 NaN
2023-12-20 1.0944 157.12 NaN
second 2023-12-08 NaN NaN 0.9438
2023-12-11 NaN NaN 0.9478
2023-12-12 NaN NaN 0.9443
2023-12-13 NaN NaN 0.9452
2023-12-14 NaN NaN 0.9490
2023-12-15 NaN NaN 0.9488
2023-12-18 NaN NaN 0.9480
2023-12-19 NaN NaN 0.9470
2023-12-20 NaN NaN 0.9460
2023-12-21 NaN NaN 0.9432
2023-12-22 NaN NaN 0.9417
first again 2023-12-14 1.0919 154.80 NaN
2023-12-15 1.0946 155.15 NaN
2023-12-18 1.0918 155.95 NaN
2023-12-19 1.0962 158.20 NaN
2023-12-20 1.0944 157.12 NaN
pd.concat([df_USD_JPY_2023, df_CHF_2023_dec], axis=1,
          keys=['USD+JPY', 'CHF only'])
USD+JPY CHF only
USD JPY CHF
Time
2023-12-08 NaN NaN 0.9438
2023-12-11 NaN NaN 0.9478
2023-12-12 NaN NaN 0.9443
2023-12-13 NaN NaN 0.9452
2023-12-14 1.0919 154.80 0.9490
2023-12-15 1.0946 155.15 0.9488
2023-12-18 1.0918 155.95 0.9480
2023-12-19 1.0962 158.20 0.9470
2023-12-20 1.0944 157.12 0.9460
2023-12-21 NaN NaN 0.9432
2023-12-22 NaN NaN 0.9417

Horizontal stacking with union

pd.concat([df_USD_JPY_2023, df_CHF_2023_dec], axis=1, join='outer')
USD JPY CHF
Time
2023-12-08 NaN NaN 0.9438
2023-12-11 NaN NaN 0.9478
2023-12-12 NaN NaN 0.9443
2023-12-13 NaN NaN 0.9452
2023-12-14 1.0919 154.80 0.9490
2023-12-15 1.0946 155.15 0.9488
2023-12-18 1.0918 155.95 0.9480
2023-12-19 1.0962 158.20 0.9470
2023-12-20 1.0944 157.12 0.9460
2023-12-21 NaN NaN 0.9432
2023-12-22 NaN NaN 0.9417
pd.concat([df_USD_JPY_2023, df_CHF_2023_dec], axis=1, join='outer')
# here, outer means to take the union of all the rows
USD JPY CHF
Time
2023-12-08 NaN NaN 0.9438
2023-12-11 NaN NaN 0.9478
2023-12-12 NaN NaN 0.9443
2023-12-13 NaN NaN 0.9452
2023-12-14 1.0919 154.80 0.9490
2023-12-15 1.0946 155.15 0.9488
2023-12-18 1.0918 155.95 0.9480
2023-12-19 1.0962 158.20 0.9470
2023-12-20 1.0944 157.12 0.9460
2023-12-21 NaN NaN 0.9432
2023-12-22 NaN NaN 0.9417
# filling missing values
pd.concat([df_USD_JPY_2023, df_CHF_2023_dec], axis=1, join='outer').fillna(0.0)
USD JPY CHF
Time
2023-12-08 0.0000 0.00 0.9438
2023-12-11 0.0000 0.00 0.9478
2023-12-12 0.0000 0.00 0.9443
2023-12-13 0.0000 0.00 0.9452
2023-12-14 1.0919 154.80 0.9490
2023-12-15 1.0946 155.15 0.9488
2023-12-18 1.0918 155.95 0.9480
2023-12-19 1.0962 158.20 0.9470
2023-12-20 1.0944 157.12 0.9460
2023-12-21 0.0000 0.00 0.9432
2023-12-22 0.0000 0.00 0.9417

Horizontal stacking with intersection

# here, inner means to take the **intersection** of all the rows
pd.concat([df_USD_JPY_2023, df_CHF_2023_dec], axis=1, join='inner')
USD JPY CHF
Time
2023-12-14 1.0919 154.80 0.9490
2023-12-15 1.0946 155.15 0.9488
2023-12-18 1.0918 155.95 0.9480
2023-12-19 1.0962 158.20 0.9470
2023-12-20 1.0944 157.12 0.9460