合并两列数据帧的替代解决方案



我一直在尝试为以下代码找到一个替代方案(可能更优雅(,但没有任何运气。这是我的代码:

import os
import pandas as pd
os.chdir(os.getcwd())
df1 = pd.DataFrame({'Month': [1]*6 + [13]*6,
'Temp': [0, 1, 2, 3, 4, 5]*2,
'Place': [12, 53, 6, 11, 9, 10, 0, 0, 0, 0, 0, 0],
'Place2': [1, 0, 23, 14, 9, 8, 0, 0, 0, 0, 0, 0],
'Place3': [2, 64, 24, 66, 14, 21, 0, 0, 0, 0, 0, 0]}
)
df2 = pd.DataFrame({'Month': [13] * 6,
'Temp': [0, 1, 2, 3, 4, 5],
'Place': [1, 22, 333, 444, 55, 6]})
# Here it creates new columns "Place_y" and "Place_x".
# I want to avoid this if possible.
df_merge = pd.merge(df1, df2, how='left',
left_on=['Temp', 'Month'],
right_on=['Temp', 'Month'])
df_merge.fillna(0, inplace=True)
add_not_nan = lambda x: x['Place_x'] if pd.isnull(x['Place_y']) else x['Place_y']
df_merge['Place'] = df_merge.apply(add_not_nan, axis=1)
df_merge.drop(['Place_x', 'Place_y'], axis=1, inplace=True)
print(df_merge)

我试图实现的是基于";月份";以及";温度";列,同时保留缺失值的0。我想知道是否有任何方法可以合并数据帧而不创建_x和_y列(基本上是跳过创建和删除这些列的方法(。

输入:

  • 第一个数据帧
Month  Temp  Place  Place2  Place3
0       1     0     12       1       2
1       1     1     53       0      64
2       1     2      6      23      24
3       1     3     11      14      66
4       1     4      9       9      14
5       1     5     10       8      21
6      13     0      0       0       0
7      13     1      0       0       0
8      13     2      0       0       0
9      13     3      0       0       0
10     13     4      0       0       0
11     13     5      0       0       0 
  • 第二个数据帧
Month  Temp  Place
0     13     0      1
1     13     1     22
2     13     2    333
3     13     3    444
4     13     4     55
5     13     5      6

输出:

  • 合并后
Month  Temp  Place_x  Place2  Place3  Place_y
0       1     0       12       1       2      NaN
1       1     1       53       0      64      NaN
2       1     2        6      23      24      NaN
3       1     3       11      14      66      NaN
4       1     4        9       9      14      NaN
5       1     5       10       8      21      NaN
6      13     0        0       0       0      1.0
7      13     1        0       0       0     22.0
8      13     2        0       0       0    333.0
9      13     3        0       0       0    444.0
10     13     4        0       0       0     55.0
11     13     5        0       0       0      6.0
  • 决赛(需要(
Month  Temp  Place2  Place3  Place
0       1     0       1       2    0.0
1       1     1       0      64    0.0
2       1     2      23      24    0.0
3       1     3      14      66    0.0
4       1     4       9      14    0.0
5       1     5       8      21    0.0
6      13     0       0       0    1.0
7      13     1       0       0   22.0
8      13     2       0       0  333.0
9      13     3       0       0  444.0
10     13     4       0       0   55.0
11     13     5       0       0    6.0

似乎不需要df1中的Place列,您可以在合并前将其删除:

(df1.drop('Place', axis=1)
.merge(df2, how='left', on=['Temp', 'Month'])
.fillna({'Place': 0}))
#    Month  Temp  Place2  Place3  Place
#0       1     0       1       2    0.0
#1       1     1       0      64    0.0
#2       1     2      23      24    0.0
#3       1     3      14      66    0.0
#4       1     4       9      14    0.0
#5       1     5       8      21    0.0
#6      13     0       0       0    1.0
#7      13     1       0       0   22.0
#8      13     2       0       0  333.0
#9      13     3       0       0  444.0
#10     13     4       0       0   55.0
#11     13     5       0       0    6.0

如果您不知道有多少这样的列,并且如果您总是想将第二个数据帧中的列包括在内,以用于未用作键列的重叠列名,那么您可以使用pd.merge的后缀参数屏蔽这些变量,然后使用pandas.DataFrame.filter:过滤掉带有屏蔽字符的列

df1.merge(df2,
how='left', 
left_on=['Temp', 'Month'],
right_on=['Temp', 'Month'],
suffixes=('##@', '')).fillna(0).filter(regex='.*(?<!##@)$')      

输出:

Month  Temp  Place2  Place3  Place
0       1     0       1       2    0.0
1       1     1       0      64    0.0
2       1     2      23      24    0.0
3       1     3      14      66    0.0
4       1     4       9      14    0.0
5       1     5       8      21    0.0
6      13     0       0       0    1.0
7      13     1       0       0   22.0
8      13     2       0       0  333.0
9      13     3       0       0  444.0
10     13     4       0       0   55.0
11     13     5       0       0    6.0

显然,您还可以在合并前通过检查第一个数据帧中第二个数据帧的列的存在来过滤掉这些列:

cols=[col for col in df1.columns if col in ('Temp', 'Month') or col not in df2.columns ]
df1[cols].merge(df2, how='left', 
left_on=['Temp', 'Month'],
right_on=['Temp', 'Month']).fillna(0)
Month  Temp  Place2  Place3  Place
0       1     0       1       2    0.0
1       1     1       0      64    0.0
2       1     2      23      24    0.0
3       1     3      14      66    0.0
4       1     4       9      14    0.0
5       1     5       8      21    0.0
6      13     0       0       0    1.0
7      13     1       0       0   22.0
8      13     2       0       0  333.0
9      13     3       0       0  444.0
10     13     4       0       0   55.0
11     13     5       0       0    6.0

最新更新