如何解决通过基于具有不同索引的唯一值将值从第一数据帧更新到第二数据帧来迭代每一行,否则追加并分配新的ID
如果唯一值匹配,则尝试将每行从df1更新为df2。如果没有,请将行添加到df2并分配新的ID列。
df1(无ID列):
unique_value Status Price
0 xyz123 bad 6.67
1 eff987 bad 1.75
2 efg125 okay 5.77
df2:
unique_value Status Price ID
0 xyz123 good 1.25 1000
1 xyz123 good 1.25 1000
2 xyz123 good 1.25 1000
3 xyz123 good 1.25 1000
4 xyz985 bad 1.31 1001
5 abc987 okay 4.56 1002
6 eff987 good 9.85 1003
7 asd541 excellent 8.85 1004
更新的df2所需的输出:
unique_value Status Price ID
0 xyz123 bad 6.67 1000 <-updated
1 xyz123 bad 6.67 1000 <-updated
2 xyz123 bad 6.67 1000 <-updated
3 xyz123 bad 6.67 1000 <-updated
4 xyz985 bad 1.31 1001
5 abc987 okay 4.56 1002
6 eff987 bad 1.75 1003 <-updated
7 asd541 excellent 8.85 1004
8 efg125 okay 5.77 1005 <-appended
这是我到目前为止所做的:
for i in range(0,len(df1)):
if df1['unique_value'].isin(df2['unique_value'])[i] == True:
... update row in df2
else:
df2 = df2.append(i)
... assign row with new ID using pd.factorize and ID value at df2['ID'].max()+1
请注意,我最初使用pd.factorize
来基于df2
的unique_value分配ID,其值以1000
,1001
(依此类推)使用以下代码: {1}}
我尝试使用此解决方案(Updating a dataframe rows based on another dataframe rows),但是它索引了我的unique_value列,这阻止了我迭代另一个向前移动的数据集。
有什么办法可以编写脚本?
谢谢!
解决方法
我实现这两个部分的策略解释如下。
- 更新现有行:只要将
df2
中行的形状正确地重塑为df1
,就可以通过broadcasting更新(1,3)
。pandas
中的广播概念与numpy
中的广播概念相同。 - 追加新行:假设连续索引从
0
开始递增,则可以通过直接调用df2.loc[len(df2),:] = ...
轻松地追加新行,其中len(df2)
是下一个未使用的自然数索引栏。例如:this answer。
此外,在我的解决方案中构造了2个其他状态变量,因为我认为它们比每次必须搜索整个df2
更为有效。如果这不是问题,当然可以将其丢弃。
代码:
# additional state variables
# 1. for the ID to be added
current_max_id = df2["ID"].max()
# 2. for matching unique_values,avoiding searching df2["unique_value"] every time
current_value_set = set(df2["unique_value"].values)
# match unique_value's using the state variable instead of `df2`
mask = df1["unique_value"].isin(current_value_set)
for i in range(len(df1)):
# current unique_value from df1
uv1 = df1["unique_value"][i]
# 1. update existing
if mask[i]:
# broadcast df1 into the matched rows in df2 (mind the shape)
df2.loc[df2["unique_value"] == uv1,["unique_value","Status","Price"]] = df1.iloc[i,:].values.reshape((1,3))
# 2. append new
else:
# update state variables
current_max_id += 1
current_value_set.add(uv1)
# append the row (assumes df2.index=[0,1,2,3,...])
df2.loc[len(df2),:] = [df1.iloc[i,0],df1.iloc[i,1],2],current_max_id]
输出:
df2
Out[45]:
unique_value Status Price ID
0 xyz123 bad 6.67 1000.0
1 xyz123 bad 6.67 1000.0
2 xyz123 bad 6.67 1000.0
3 xyz123 bad 6.67 1000.0
4 xyz985 bad 1.31 1001.0
5 abc987 okay 4.56 1002.0
6 eff987 bad 1.75 1003.0
7 asd541 excellent 8.85 1004.0
8 efg125 okay 5.77 1005.0
使用python 3.7,pandas 1.1.2,OS = debian 10 64位进行了测试
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。