【问题标题】:Create new column in dataframe by applying math operation to column values based on a match通过基于匹配对列值应用数学运算在数据框中创建新列
【发布时间】:2017-12-28 01:42:02
【问题描述】:

我有以下数据框:

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

我想要的输出是将每个电话号码与其前缀匹配(前缀比电话号码多)并通过将每个电话号码的通话时长乘以相应的前缀费用加上相应的前缀来计算每次通话的费用率。

输出例子

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 键匹配然后使用该匹配键的相应值执行操作。但是不起作用,还想知道是否有更好的选择。

【问题讨论】:

    标签: python-2.7 pandas dictionary dataframe startswith


    【解决方案1】:

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

    >> 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
    

    注意

    • 如果有多个前缀,我选择最大长度的一个;
    • 如果没有特定电话的前缀,我会用默认零值填充其长度(然后s.phone[:s.prefix_len] 将产生一个空前缀,pd.merge 将从结果中删除这些电话)。

    【讨论】:

    • 谢谢,这是一种简单的方法,它可以工作,但这只是一个例子,不幸的是我也有前缀不再总是只有 3 个字符长,所以我不能总是在前 3 个字母。
    • @Ana 检查电话可能带有不同长度前缀的情况的更新答案。
    • 此功能是否有模块要求?我收到以下错误:TypeError: max() got an unexpected keyword argument
    • @Ana 是的,对不起,我没有提到 python 版本,实际上default 参数是针对 python3.4+ 的。我更新了使用 python2 的答案。
    • 非常感谢!感谢您的帮助和清晰的代码:)
    【解决方案2】:
    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
    

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

    【讨论】:

    • 用于问题的数据框是我有数百条日志调用记录和前缀的示例。我已经运行了代码,但它似乎将前缀与电话号码匹配,如果前缀包含在 phoen 号码中,它将匹配。例如,我的前缀 441 与电话号码 4474441 匹配
    • 通常这是不可能的,因为只有 df3[prefix] 列与也只包含前 4 个字符的 df4 匹配
    • 谢谢 有没有办法实现这个呢?只是计算可能与电话号码不同的前缀?
    • 不客气。如果您知道前缀的确切形状,则可以使用正则表达式进行尝试。同样为此,您必须知道分配前缀的“规则”
    • 所以我的意思是你必须知道分配前缀的规则。例如,如果前缀也与数字的开头完美匹配,那么正则表达式就可以了
    猜你喜欢
    • 2020-01-31
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 2016-06-15
    • 2016-03-21
    • 2022-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多