简体   繁体   English

如何根据列值和行值连接两个df?

[英]How to join two df's on the basis of column values and row values?

I have a column of df ( df1 ), let's say, column1 consisting of random months and years in the format %b-%y and column2 consisting of some numbers.我有一列 df ( df1 ),比方说, column1%b-%y格式的随机月份和年份组成,而column2由一些数字组成。 I have another df ( df2 ) which has column headers of random months and years in the same format as df1, let's say Jan-21 to Dec-21 for the sake of simplicity.我有另一个 df ( df2 ),它具有与 df1 格式相同的随机月份和年份的列标题,为了简单起见,假设为 Jan-21 到 Dec-21。 Both df's also have some columns in common.两个 df 也有一些共同的columns

Is there a way to join df1 and df2 on the basis of the columns and populate df2 with numbers from column2 ?有没有办法在列的基础上加入df1df2并用column2中的数字填充 df2 ?

df1, df1,

    column1 column3 column4 column5 column6
0   ABCD    CT      AA      Apr-21  123
1   ABCD    CT      EE      Jun-21  24
2   ABCD    CT      CS      Jul-21  123
3   ABCD    CT      UUU     Jan-21  123
4   ABCD    CT      MMM     Apr-20  432
5   ABCD    CT      CCC     Aug-21  312
6   ABCD    CP      AA      Jul-21  4
7   ABCD    CP      EE      Jun-21  2
8   ABCD    CP      CS      Nov-21  0
9   ABCD    CP     UUU      Mar-21  34
10  ABCD    CP     MMM      Sep-21  234
11  ABCD    CP     CCC      Oct-21  123

df2 is the following and the format is fixed, need to populate it with column6 on the basis of column5 with columns 1,3,4 the same in df2. df2如下,格式固定,需要在column5的基础上用column6填充,df2中的1,3,4列相同。

{'column1': ['ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD'], 'column2': ['V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V'], 'column3': ['CT', 'CT', 'CT', 'CT', 'CT', 'CT', 'CT', 'CT', 'CT', 'CT', 'CT', 'CT', 'CP', 'CP', 'CP', 'CP', 'CP', 'CP', 'CP', 'CP', 'CP', 'CP', 'CP', 'CP'], 'column4': ['OCP', 'AC', 'TC', 'AA', 'EE', 'CS', 'UUU', 'MMM', 'CCC', 'TOQ', 'OC', 'FR', 'OCP', 'AC', 'TC', 'AA', 'EE', 'CS', 'UUU', 'MMM', 'CCC', 'TOQ', 'OC', 'FR'], 'Jan-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], 'Feb-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], 'Mar-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], 'Apr-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], 'May-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], 'Jun-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], 'Jul-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], 'Aug-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], 'Sep-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], 'Oct-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], 'Nov-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], 'Dec-21': [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]}

The final output should look like this,最终的 output 应该是这样的,

在此处输入图像描述 I cannot use pivot because I want to retain the month column headers in df2.我不能使用 pivot 因为我想在 df2 中保留月份列标题。

You do not need to introduce "placeholder" months to achieve this.您不需要引入“占位符”月份来实现这一点。 You can set a DatetimeIndex and reindex your DataFrame to fill in the missing dates.您可以设置 DatetimeIndex 并重新索引您的 DataFrame 以填写缺失的日期。 Afterward, it's just a pivot table.之后,它只是一个 pivot 表。

Here is an example:这是一个例子:

import pandas as pd
import io
from datetime import (date, datetime)

df1_text = """
index  column1 column3 column4 column5 column6
0   ABCD    CT      AA      Apr-21  123
1   ABCD    CT      EE      Jun-21  24
2   ABCD    CT      CS      Jul-21  123
3   ABCD    CT      UUU     Jan-21  123
4   ABCD    CT      MMM     Apr-20  432
5   ABCD    CT      CCC     Aug-21  312
6   ABCD    CP      AA      Jul-21  4
7   ABCD    CP      EE      Jun-21  2
8   ABCD    CP      CS      Nov-21  0
9   ABCD    CP     UUU      Mar-21  34
10  ABCD    CP     MMM      Sep-21  234
11  ABCD    CP     CCC      Oct-21  123
"""


def s2d(s):
    return(datetime.strptime(s, '%b-%y'))


df1 = pd.read_csv(io.StringIO(df1_text), sep='\s+',
                  index_col=[0], converters={'column5': s2d})

# set datetime as index and group by columns
df1 = df1.set_index('column5').groupby(['column1', 'column3', 'column4'])

# reindex by full daterange
df1 = df1.apply(lambda x: x.reindex(pd.date_range(
    date(2021, 1, 1), date(2021, 12, 31), freq='MS')))

# drop extra columns
df1.drop(['column1', 'column3', 'column4'], axis=1, inplace=True)

# reset group by index
df1.reset_index(['column1', 'column3', 'column4'], inplace=True)

# reset datetime index
df1.reset_index(inplace=True)

# pivot table
df1 = df1.pivot_table(
    index=['column1', 'column3', 'column4'],
    columns='index',
    values='column6',
    dropna=False  # make sure empty months do not get dropped
)

# reformat the columns back to '%b-&y'
df1.columns = [datetime.strftime(d, '%b-%y') for d in df1.columns]

# reset_index
df1.reset_index(inplace=True)

# df2 without months
df2 = pd.DataFrame({
    'column1': ['ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD',
                'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD',
                'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD', 'ABCD'],
    'column2': ['V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V',
                'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V', 'V'],
    'column3': ['CT', 'CT', 'CT', 'CT', 'CT', 'CT', 'CT', 'CT', 'CT', 'CT',
                'CT', 'CT', 'CP', 'CP', 'CP', 'CP', 'CP', 'CP', 'CP', 'CP',
                'CP', 'CP', 'CP', 'CP'],
    'column4': ['OCP', 'AC', 'TC', 'AA', 'EE', 'CS', 'UUU', 'MMM', 'CCC', 'TOQ',
                'OC', 'FR', 'OCP', 'AC', 'TC', 'AA', 'EE', 'CS', 'UUU', 'MMM',
                'CCC', 'TOQ', 'OC', 'FR']})

# merge df2 with df1
df2 = df2.merge(df1, on=['column1', 'column3', 'column4'], how='left')

You can try pivot_table with set_index+fillna您可以使用set_index+fillna尝试pivot_table

cols = ['column1', 'column3', 'column4']
u = df1.pivot_table(index=cols,columns='column5',values='column6')
out = df2.set_index(cols).fillna(u).reset_index().reindex(df2.columns,axis=1)

Output: Output:

print(out)

   column1 column2 column3 column4  Jan-21  Feb-21  Mar-21  Apr-21  May-21  \
0     ABCD       V      CT     OCP     NaN     NaN     NaN     NaN     NaN   
1     ABCD       V      CT      AC     NaN     NaN     NaN     NaN     NaN   
2     ABCD       V      CT      TC     NaN     NaN     NaN     NaN     NaN   
3     ABCD       V      CT      AA     NaN     NaN     NaN   123.0     NaN   
4     ABCD       V      CT      EE     NaN     NaN     NaN     NaN     NaN   
5     ABCD       V      CT      CS     NaN     NaN     NaN     NaN     NaN   
6     ABCD       V      CT     UUU   123.0     NaN     NaN     NaN     NaN   
7     ABCD       V      CT     MMM     NaN     NaN     NaN     NaN     NaN   
8     ABCD       V      CT     CCC     NaN     NaN     NaN     NaN     NaN   
9     ABCD       V      CT     TOQ     NaN     NaN     NaN     NaN     NaN   
10    ABCD       V      CT      OC     NaN     NaN     NaN     NaN     NaN   
11    ABCD       V      CT      FR     NaN     NaN     NaN     NaN     NaN   
12    ABCD       V      CP     OCP     NaN     NaN     NaN     NaN     NaN   
13    ABCD       V      CP      AC     NaN     NaN     NaN     NaN     NaN   
14    ABCD       V      CP      TC     NaN     NaN     NaN     NaN     NaN   
15    ABCD       V      CP      AA     NaN     NaN     NaN     NaN     NaN   
16    ABCD       V      CP      EE     NaN     NaN     NaN     NaN     NaN   
17    ABCD       V      CP      CS     NaN     NaN     NaN     NaN     NaN   
18    ABCD       V      CP     UUU     NaN     NaN    34.0     NaN     NaN   
19    ABCD       V      CP     MMM     NaN     NaN     NaN     NaN     NaN   
20    ABCD       V      CP     CCC     NaN     NaN     NaN     NaN     NaN   
21    ABCD       V      CP     TOQ     NaN     NaN     NaN     NaN     NaN   
22    ABCD       V      CP      OC     NaN     NaN     NaN     NaN     NaN   
23    ABCD       V      CP      FR     NaN     NaN     NaN     NaN     NaN   

    Jun-21  Jul-21  Aug-21  Sep-21  Oct-21  Nov-21  Dec-21  
0      NaN     NaN     NaN     NaN     NaN     NaN     NaN  
1      NaN     NaN     NaN     NaN     NaN     NaN     NaN  
2      NaN     NaN     NaN     NaN     NaN     NaN     NaN  
3      NaN     NaN     NaN     NaN     NaN     NaN     NaN  
4     24.0     NaN     NaN     NaN     NaN     NaN     NaN  
5      NaN   123.0     NaN     NaN     NaN     NaN     NaN  
6      NaN     NaN     NaN     NaN     NaN     NaN     NaN  
7      NaN     NaN     NaN     NaN     NaN     NaN     NaN  
8      NaN     NaN   312.0     NaN     NaN     NaN     NaN  
9      NaN     NaN     NaN     NaN     NaN     NaN     NaN  
10     NaN     NaN     NaN     NaN     NaN     NaN     NaN  
11     NaN     NaN     NaN     NaN     NaN     NaN     NaN  
12     NaN     NaN     NaN     NaN     NaN     NaN     NaN  
13     NaN     NaN     NaN     NaN     NaN     NaN     NaN  
14     NaN     NaN     NaN     NaN     NaN     NaN     NaN  
15     NaN     4.0     NaN     NaN     NaN     NaN     NaN  
16     2.0     NaN     NaN     NaN     NaN     NaN     NaN  
17     NaN     NaN     NaN     NaN     NaN     0.0     NaN  
18     NaN     NaN     NaN     NaN     NaN     NaN     NaN  
19     NaN     NaN     NaN   234.0     NaN     NaN     NaN  
20     NaN     NaN     NaN     NaN   123.0     NaN     NaN  
21     NaN     NaN     NaN     NaN     NaN     NaN     NaN  
22     NaN     NaN     NaN     NaN     NaN     NaN     NaN  
23     NaN     NaN     NaN     NaN     NaN     NaN     NaN  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM