pandas操作的新手,我有这两个数据帧:
import pandas as pd
df = pd.DataFrame({'name': ['a','a','b','b','c','c'], 'id':[1,2,1,2,1,2], 'val1':[0,0,0,0,0,0],'val2':[0,0,0,0,0,0],'val3':[0,0,0,0,0,0]})
id name val1 val2 val3
0 1 a 0 0 0
1 2 a 0 0 0
2 1 b 0 0 0
3 2 b 0 0 0
4 1 c 0 0 0
5 2 c 0 0 0
subdf = pd.DataFrame({'name': ['a','b','c'], 'id':[1,1,2],'val1':[0.3,0.4,0.7], 'val2':[4,5,4]}
id name val1 val2
0 1 a 0.3 4
1 1 b 0.4 5
2 2 c 0.7 4
我想获得输出:
id name val1 val2 val3
0 1 a 0.3 4 0
1 2 a 0.0 0 0
2 1 b 0.4 5 0
3 2 b 0.0 0 0
4 1 c 0.0 0 0
5 2 c 0.7 4 0
但我没有抓住替换的例子,只是添加了我看到的教程中的列/行!
答案 0 :(得分:6)
这需要几个步骤,在匹配的列上留下merge
,这将创建' x'并且' y'哪里有冲突:
In [25]:
merged = df.merge(subdf, on=['id', 'name'], how='left')
merged
Out[25]:
id name val1_x val2_x val3 val1_y val2_y
0 1 a 0 0 0 0.3 4
1 2 a 0 0 0 NaN NaN
2 1 b 0 0 0 0.4 5
3 2 b 0 0 0 NaN NaN
4 1 c 0 0 0 NaN NaN
5 2 c 0 0 0 0.7 4
In [26]:
# take the values that of interest from the clashes
merged['val1'] = np.max(merged[['val1_x', 'val1_y']], axis=1)
merged['val2'] = np.max(merged[['val2_x', 'val2_y']], axis=1)
merged
Out[26]:
id name val1_x val2_x val3 val1_y val2_y val1 val2
0 1 a 0 0 0 0.3 4 0.3 4
1 2 a 0 0 0 NaN NaN 0.0 0
2 1 b 0 0 0 0.4 5 0.4 5
3 2 b 0 0 0 NaN NaN 0.0 0
4 1 c 0 0 0 NaN NaN 0.0 0
5 2 c 0 0 0 0.7 4 0.7 4
In [27]:
# drop the additional columns
merged = merged.drop(labels=['val1_x', 'val1_y','val2_x', 'val2_y'], axis=1)
merged
Out[27]:
id name val3 val1 val2
0 1 a 0 0.3 4
1 2 a 0 0.0 0
2 1 b 0 0.4 5
3 2 b 0 0.0 0
4 1 c 0 0.0 0
5 2 c 0 0.7 4
另一种方法是将两个df' id'和' name'然后拨打update
:
In [30]:
df = df.sort(columns=['id','name'])
subdf = subdf.sort(columns=['id','name'])
df.update(subdf)
df
Out[30]:
id name val1 val2 val3
0 1 a 0.3 4 0
2 2 c 0.7 4 0
4 1 c 0.0 0 0
1 1 b 0.4 5 0
3 2 b 0.0 0 0
5 2 c 0.0 0 0
答案 1 :(得分:1)
update
方法更新版本。受Nic
的启发我用concat
做到了这一点,但不如下面用update
做到的那样优雅,并且复制了DataFrame,我相信使用较大的表可能会导致内存和/或速度问题。
df = pd.DataFrame({'name': list('aabbcc'), 'id':[1,2]*3, 'val1':[0]*6,'val2':[0]*6,'val3':[0]*6})
subdf = pd.DataFrame({'name': list('abc'), 'id':[1,1,2],'val1':[0.3,0.4,0.7], 'val2':[4,5,4]})
df.set_index(['name','id'], inplace=True)
df.update(subdf.set_index(['name','id']))
df.reset_index(inplace=True)
df
结果:
name id val1 val2 val3
0 a 1 0.3 4.0 0
1 a 2 0.0 0.0 0
2 b 1 0.4 5.0 0
3 b 2 0.0 0.0 0
4 c 1 0.0 0.0 0
5 c 2 0.7 4.0 0
次要缺点是pandas.DataFrame.update
会更改JAB指出的dtypes
答案 2 :(得分:0)
以上答案第二部分的sort
函数已被弃用。使用Pandas 0.20+实现相同效果的用户的代码是:
df1 = pd.DataFrames(usecols=['A', 'B']) # You want to merge TO this
df2 = pd.DataFrames(usecols=['A', 'B']) # You want to merge FROM this
df1 = df1.sort_values (by=['A', 'B'])
df2 = df2.sort_values (by=['A', 'B'])
df1.update(df2)
答案 3 :(得分:0)
另一种解决方案是,如果val1
和val2
的所有值均为0,则可以删除列
df = pd.DataFrame({'name': ['a','a','b','b','c','c'], 'id':[1,2,1,2,1,2], 'val1':[0,0,0,0,0,0],'val2':[0,0,0,0,0,0],'val3':[0,0,0,0,0,0]})
subdf = pd.DataFrame({'name': ['a','b','c'], 'id':[1,1,2],'val1':[0.3,0.4,0.7], 'val2':[4,5,4]})
print (df)
id name val1 val2 val3
0 1 a 0 0 0
1 2 a 0 0 0
2 1 b 0 0 0
3 2 b 0 0 0
4 1 c 0 0 0
5 2 c 0 0 0
print (subdf)
id name val1 val2
0 1 a 0.3 4
1 1 b 0.4 5
2 2 c 0.7 4
df = df.drop(['val1', 'val2'], axis=1)
print (df)
id name val3
0 1 a 0
1 2 a 0
2 1 b 0
3 2 b 0
4 1 c 0
5 2 c 0
然后进行合并
df = df.merge(subdf, on=['id', 'name'], how='left')
print (df)
name id val3 val1 val2
0 a 1 0 0.3 4.0
1 a 2 0 NaN NaN
2 b 1 0 0.4 5.0
3 b 2 0 NaN NaN
4 c 1 0 NaN NaN
5 c 2 0 0.7 4.0
最后使用fillna
替换NaN
值。
df['val1'].fillna(0, inplace=True)
df['val2'].fillna(0, inplace=True)
print (df)
name id val3 val1 val2
0 a 1 0 0.3 4.0
1 a 2 0 0.0 0.0
2 b 1 0 0.4 5.0
3 b 2 0 0.0 0.0
4 c 1 0 0.0 0.0
5 c 2 0 0.7 4.0
要对列进行排序,请使用
column_names = ['id', 'name', 'val1', 'val2', 'val3']
df = df.reindex(columns=column_names)
print (df)
id name val1 val2 val3
0 1 a 0.3 4.0 0
1 2 a 0.0 0.0 0
2 1 b 0.4 5.0 0
3 2 b 0.0 0.0 0
4 1 c 0.0 0.0 0
5 2 c 0.7 4.0 0
然后将列解析为int使用
df['val2'] = df['val2'].astype(int)
print (df)
id name val1 val2 val3
0 1 a 0.3 4 0
1 2 a 0.0 0 0
2 1 b 0.4 5 0
3 2 b 0.0 0 0
4 1 c 0.0 0 0
5 2 c 0.7 4 0