基于引用另一列的参考表更新Pandas Dataframe列的问题

时间:2018-01-09 17:30:02

标签: python pandas csv dictionary dataframe

我有一个数据框,我正在尝试根据外部参考表中的信息进行更新(目前这是一个很小的~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

目前,我将引用表导入字典(作为整数),但是当我将其与数据帧匹配时,结果(value2)将返回NaN。我认为我的问题可能在于匹配的代码,目前看起来像这样:

df['value2'] = df['value1'] * (df["company"].map(vd)/100)

我在这里走在正确的轨道上吗?这是我第一次使用大熊猫,所以我可能会遗漏一些明显的东西。

谢谢!

编辑:意外忘记混淆一个变量。 “vd”只是导入后的字典名称。

1 个答案:

答案 0 :(得分:2)

到目前为止,{p> 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

选项1
map

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

选项2
replace

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

选项3
merge

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在这里是明显的赢家。