基于针对另一列的参考表更新 Pandas 数据框列的问题
Posted
技术标签:
【中文标题】基于针对另一列的参考表更新 Pandas 数据框列的问题【英文标题】:Issue With Updating Pandas Dataframe Column Based on Reference Table Targeting Another Column 【发布时间】:2018-06-18 19:30:52 【问题描述】:我有一个数据框,我正在尝试根据我在外部参考表中的信息(目前是一个小的 ~20 条目 csv)来更新它,我在弄清楚如何获取它时遇到了一些困难上班。
数据框如下所示:
id company value1 value2
1 foo 10.00 0.00
2 bar 10.00 0.00
3 lorem 15.00 0.00
4 ipsum 10.00 0.00
5 foo 50.00 0.00
6 lorem 40.00 0.00
7 foo 0.00 0.00
参考表 csv 包含将 value1 乘以得到 value2 的百分比,就像这样(它们最初是小数,但 vd = pd.read_csv('$name.csv', index_col=0).to_dict() 导致浮动点问题,所以我改为更改参考表):
company percentage
foo 15
bar 50
ipsum 40
我正在寻找如下所示的输出:
id company value1 value2
1 foo 10.00 1.50
2 bar 10.00 5.00
3 lorem 15.00 15.00
4 ipsum 10.00 4.00
5 foo 50.00 7.50
6 lorem 40.00 40.00
7 foo 0.00 0.00
目前,我将引用表导入字典(作为整数),但是当我将其与数据框匹配时,结果(值 2)以 NaN 形式返回。我认为我的问题可能与匹配代码有关,目前看起来像这样:
df['value2'] = df['value1'] * (df["company"].map(vd)/100)
我在正确的轨道上吗?这是我第一次使用 pandas,所以我可能会遗漏一些明显的东西。
谢谢!
编辑:不小心忘记混淆一个变量。 “vd”只是字典导入后的名称。
【问题讨论】:
我想我之前误解了。你能告诉我vd
是什么吗?如果它是一个 DataFrame,你可以使用 vd.set_index('company')['percentage']
而不是 vd
,但你需要展示你是如何构建它们的。
不,你以前似乎是对的。摆脱字典,而是使用 vd = pd.read_csv('$name.csv', index_col=0, squeeze=True) 解决了参考表中的问题,我不在乎那些不在参考表中的(因为它们马上就被删除了)。现在我只需要添加边界检查(因为前面部分中的任何负数都需要为 0 而不是负数),然后就可以开始了。谢谢!
也鼓励你看看我的回答 ;-)
@ZuR4ruukmT0YPwgs 立即尝试... ;-) 此外,如果它回答了您的问题,您可以通过单击答案旁边的灰色复选标记将其切换为绿色来接受它。
请看我上面的评论。 ^
【参考方案1】:
map
是迄今为止完成您正在做的事情的最快方式。但这里有几个选择,以及它们的性能。
设置
首先,df
-
df
id company value1 value2
0 1 foo 10.0 0.0
1 2 bar 10.0 0.0
2 3 lorem 15.0 0.0
3 4 ipsum 10.0 0.0
4 5 foo 50.0 0.0
5 6 lorem 40.0 0.0
接下来,vd
-
vd = pd.read_csv('$name.csv')
vd = vd.set_index('company').percentage
或者,
vd = pd.read_csv('$name.csv', index_col=0, squeeze=True) # @ayhan's suggestion
vd
company
foo 15
bar 50
ipsum 40
Name: percentage, dtype: int64
选项 1map
df.value2 = df.value1 * df.company.map(vd).fillna(100).div(100)
df
id company value1 value2
0 1 foo 10.0 1.5
1 2 bar 10.0 5.0
2 3 lorem 15.0 15.0
3 4 ipsum 10.0 4.0
4 5 foo 50.0 7.5
5 6 lorem 40.0 40.0
选项 2replace
v = pd.to_numeric(df.company.replace(vd), errors='coerce')
df.value2 = df.value1 * v.fillna(100) / 100
df
id company value1 value2
0 1 foo 10.0 1.5
1 2 bar 10.0 5.0
2 3 lorem 15.0 15.0
3 4 ipsum 10.0 4.0
4 5 foo 50.0 7.5
5 6 lorem 40.0 40.0
选项 3merge
df = df.merge(
(vd / 100).to_frame(),
left_on='company',
right_index=True,
how='left'
).fillna(1)
df.value2 = df.value1 * df.percentage
del df['percentage']
df
id company value1 value2
0 1 foo 10.0 1.5
1 2 bar 10.0 5.0
2 3 lorem 15.0 15.0
3 4 ipsum 10.0 4.0
4 5 foo 50.0 7.5
5 6 lorem 40.0 40.0
性能
df = pd.concat([df] * 10000, ignore_index=True)
%timeit df.value1 * df.company.map(vd).fillna(100).div(100)
100 loops, best of 3: 6.07 ms per loop
%timeit df.value1 * pd.to_numeric(df.company.replace(vd), errors='coerce').fillna(100) / 100
10 loops, best of 3: 65.6 ms per loop
%%timeit
df2 = df.merge((vd / 100).to_frame(), left_on='company', right_index=True, how='left').fillna(1)
df2.value2 = df2.value1 * df2.percentage
del df2['percentage']
100 loops, best of 3: 13.1 ms per loop
map
显然是这里的赢家。
【讨论】:
以上是关于基于针对另一列的参考表更新 Pandas 数据框列的问题的主要内容,如果未能解决你的问题,请参考以下文章