通过基于匹配对列值应用数学运算来在数据框中创建新列

Create new column in dataframe by applying math operation to column values based on a match

我有以下数据框:

df1
name  phone  duration(m)
Luisa 443442  1
Jack  442334  6
Matt  442212  2
Jenny 453224  1

df2
prefix charge rate
443     0.8   0.3
446     0.8   0.4
442     0.6   0.1
476     0.8   0.3

我想要的输出是将每个 phone 号码与其前缀匹配(前缀比 phone 号码多)并通过乘以每个呼叫的持续时间来计算每次呼叫的费用phone号码按相应前缀加相应费率。

输出示例

df1
    name  phone  duration(m) bill
    Luisa 443442  1          (example: 1x0.3+0.8)
    Jack  442334  6          (example: 6x0.1+0.6)
    Matt  442212  2
    Jenny 453224  1

我的想法是将 df2 转换为像这样的字典 dict={'443':[0.3,0.8],'442':[0.1,0.6]...} 这样我就可以将每个数字与dict 键,然后使用该匹配键的相应值执行操作。但是不工作,也想知道是否有更好的选择。

df1 = pd.DataFrame({'name':["Louisa","Jack","Matt","Jenny"],'phone':[443442,442334,442212,453224],'duration':[1,6,2,1]})
df2 = pd.DataFrame({'prefix':[443,446,442,476],'charge':[0.8,0.8,0.6,0.8],'rate':[0.3,0.4,0.1,0.3]})

df3=pd.concat((df1,df2),axis=1)

df4=pd.DataFrame({"phone_pref":df3["phone"].astype(str).str[:3]})
df4=df4["phone_pref"].drop_duplicates()

df3["bill"]=None
for j in range(len(df4)):
    for i in range(len(df3["prefix"])):
        if df3.loc[i,"prefix"]==int(df4.iloc[j]):
            df3.loc[i,"bill"]=df3.loc[i,"duration"]*df3.loc[i,"charge"]+df3.loc[i,"rate"]
print(df3)

   duration    name   phone  charge  prefix  rate  bill
0         1  Louisa  443442     0.8     443   0.3   1.1
1         6    Jack  442334     0.8     446   0.4  None
2         2    Matt  442212     0.6     442   0.1   1.3
3         1   Jenny  453224     0.8     476   0.3  None

bill 列中的 None 值是因为在您的示例中没有 phone 号码具有前缀 446 或 476,因此它们不在 df4 中... 账单也是按照你在问题中给出的公式计算的

要与任意长度的前缀合并,你可以这样做

>> df1['phone'] = df1.phone.astype(str)
>> df2['prefix'] = df2.prefix.astype(str)
>> df1['prefix_len'] = df1.phone.apply(
       lambda h: max([len(p) for p in df2.prefix if h.startswith(p)] or [0]))
>> df1['prefix'] = df1.apply(lambda s: s.phone[:s.prefix_len], axis=1)
>> df1 = df1.merge(df2, on='prefix')
>> df1['bill'] = df1['duration(m)'] * df1['rate'] + df1['charge']
>> df1
   duration(m)   name    phone  prefix_len  prefix  charge  rate    bill
0            1  Luisa   443442           3     443     0.8   0.3     1.1
1            6   Jack   442334           3     442     0.6   0.1     1.2
2            2   Matt   442212           3     442     0.6   0.1     0.8

请注意

  • 如果有多个前缀,我选择长度最大的那个;
  • 如果特定 phone 没有前缀,我用默认的零值填充它的长度,(然后 s.phone[:s.prefix_len] 将产生一个空前缀,而 pd.merge 将消除那些 phones 来自结果)。