V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
smartG
V2EX  ›  问与答

妹子发给我一张公司要处理的绩效表格,我以为很简单,然而菜是原罪

  •  
  •   smartG · 2019-12-25 18:00:33 +08:00 · 4410 次点击
    这是一个创建于 1797 天前的主题,其中的信息可能已经有所发展或是发生改变。

    妹子发给我一个她们公司 100 多人的 Excel 表格,是关于员工等级评定的,有 N1,N2,N3,N4(百分制得分 /按权重 10%,20%,50%,20%计算)四项得分和总分 sum

    标准如下:

    • 如果 sum 在 90 分以上,为等级 A,80-90:等级 B,70-80:等级 C,60-70:等级 D
    • 如果在上述四项中有一项低于 60 分,等级顺降一级,两项低于 60 分,降两级

    尝试的方法:

    • 妹子自己用的 Excel 表格自带的函数,无果,目前正在手动计算等级
    • 我以前了解过 python 的一些库,知道 pandas 可以处理表格,倒腾了一会儿没有搞出来,python 语法也是现学,这段代码运行后只能显示了第二行的结果 B
    • 大佬们有什么好的处理这个表格的方法吗?,Excel 函数或者其他方法都行,手动计算其实也用不了多少时间,但是应该有更高效的方法,求教!

    代码部分( python 小白,大佬轻喷)

    import pandas as pd  
    data1=pd.read_excel("C:/Users/acer/Desktop/绩效.xlsx")  
    def final (num1):  
        if (num1==10):  
            return "A"  
        elif(num1==9):  
            return "B"  
        elif(num1==8):  
            return "C"  
        elif(num1==7):  
            return "D"  
        elif (num1==6):  
            return "E"
    
    def c_f1():  
        for i in range(5):  
            def c_f(first_number):  
                num=0  
                if(data1.iloc[i].values[1]<6):  
                    num+=1  
                elif(data1.iloc[i].values[2]<12):  
                    num+=1  
                elif(data1.iloc[i].values[3]<30):  
                    num+=1  
                elif(data1.iloc[i].values[4]<12):  
                    num+=1  
                return first_number-num  
    
            if (data1.iloc[i].values[5]>=90):
                    n1=c_f(10)
                    return final(n1)
            elif(data1.iloc[i].values[5]>=80 and data1.iloc[1].values[5]<90):
                    n1=c_f(9)
                    return final(n1)
            elif(data1.iloc[i].values[5]>=70 and data1.iloc[1].values[5]<80):
                    n1=c_f(8)
                    return final(n1)
            elif(data1.iloc[i].values[5]>=60 and data1.iloc[1].values[5]<70):
                    n1=c_f(7)
                    return final(n1)
            elif(data1.iloc[i].values[5]>=50 and data1.iloc[1].values[5]<60):
                    n1=c_f(6)
                    return final(n1)
    print(c_f1())
    
    第 1 条附言  ·  2019-12-26 09:36:40 +08:00

    感谢各位大佬,给妹子发过去了,借鉴的AlphaTr老哥贴出的在线文档:

    https://docs.qq.com/sheet/DR1J1Q1ltSGJ3ZWF1?c=F2A0A0

    我也会把各位说的方法都尝试一遍,毕竟妹子们经常用表格,嘿嘿,你们懂的

    43 条回复    2019-12-26 19:56:27 +08:00
    pzhzp
        1
    pzhzp  
       2019-12-25 18:23:55 +08:00 via iPhone
    excel 貌似 sum()-countif()*2 算一个最终总分再分级就可以实现?
    pzhzp
        2
    pzhzp  
       2019-12-25 18:24:23 +08:00 via iPhone
    @pzhzp 错了*10
    singerll
        3
    singerll  
       2019-12-25 18:28:10 +08:00 via Android
    sum-n1/60 取整-n2/60 取整-。。。。
    turan12
        4
    turan12  
       2019-12-25 18:28:53 +08:00 via iPhone
    设置一个过渡字段
    wmhx
        5
    wmhx  
       2019-12-25 18:37:20 +08:00
    用 sql 来统计 不容易么?
    happydezhangning
        6
    happydezhangning  
       2019-12-25 18:50:26 +08:00
    工具人?
    whwq2012
        7
    whwq2012  
       2019-12-25 19:02:34 +08:00 via iPhone   ❤️ 1
    楼主应该把脱敏后的表格发出来方便大神操作,推荐腾讯表格分享
    zhy0216
        8
    zhy0216  
       2019-12-25 19:13:32 +08:00
    你把 c_f 函数的 i 打印出来看看
    kokutou
        9
    kokutou  
       2019-12-25 19:23:53 +08:00 via Android
    中间过渡下。。。
    先算 sum 等级,再算低于 60 等级。
    查的时候也好查呀。
    sunmker
        10
    sunmker  
       2019-12-25 19:25:28 +08:00
    我有一个想法:

    首先,定义分数对应等级,A:10,B:9,C:8,D:7

    其次,通过 excel 的筛选功能分别筛选出“按照 sum 划分”的 ABCD,专门使用一列(比如 G )填上 ABCD 所对应的分数 10、9、8、7 (这个筛选出来后直接可以利用 excel 批量操作,下同)

    然后,在开辟四列(比如 H、I、J、K )分别用函数 =IF(A1<6,1,0) 这个判断公式来标记是否不及格,不及格记录 1,及格 0

    接着,就是阅读理解了,「如果在上述四项中有一项低于 60 分,等级顺降一级,两项低于 60 分,降两级」,这个是最多降两级( A ),还是最多 4 级( B )

    如果是情况B,直接L列=G-H-I-J-K,然后你接着用筛选功能。一次筛选L列值为10的,在M列填上A,然后依次批量填完所有的……
    如果是情况A,那你可以用L求和HIJK列,筛选,<2 的在M列=G-L,>= 2 的M列=G-2。然后筛选M列为10填写A……9填写B
    zmxnv123
        11
    zmxnv123  
       2019-12-25 19:30:37 +08:00
    想知道妹子去哪领
    zeroDev
        12
    zeroDev  
       2019-12-25 19:32:43 +08:00 via Android
    可以试试 openpyxl 库处理
    wangkun025
        13
    wangkun025  
       2019-12-25 19:33:48 +08:00
    继续用 excel,不要考虑 Python
    JCZ2MkKb5S8ZX9pq
        14
    JCZ2MkKb5S8ZX9pq  
       2019-12-25 19:35:10 +08:00
    直接 excel 插几个过程列好了,搞完还给她个简化版。
    xlcoder166
        15
    xlcoder166  
       2019-12-25 19:38:03 +08:00
    是关于员工等级评定的,有 N1,N2,N3,N4(百分制得分 /按权重 10%,20%,50%,20%计算)四项得分和总分 sum

    (N1 * 0.1) + (N2 * 0.2) + (N3 * 0.5) + (N4 * 0.2)

    如果 sum 在 90 分以上,为等级 A,80-90:等级 B,70-80:等级 C,60-70:等级 D

    a + b + c + d = result (A B C D)

    如果在上述四项中有一项低于 60 分,等级顺降一级,两项低于 60 分,降两级

    ? 这个标准有歧义啊

    1. 上诉四项低于 60 分, 这个 60 分指定那个 N1 还是 N1 * 0.1 ,
    2. 是最多降 2 级吗?


    思路

    先算总值的条件 1, 再判断条件 2 的情况
    dunn
        16
    dunn  
       2019-12-25 19:40:16 +08:00 via iPhone
    excel 多加几个辅助列
    passluo
        17
    passluo  
       2019-12-25 19:48:12 +08:00
    卧槽这个也太简单了吧……

    - sum 计算为一列 > C1
    - C1 按区间匹配出 ABCD 等,分别对应成 4321 > C2
    - countifs 统计一下每行低于 60 分单元格的数量 > C3
    - C2-C3 得出最后的分段 > C4
    - 把 C4 结果 1234 再对应回 DBCA > C5
    - 把 C1-C4 隐藏……

    电子表格这种系统的设计就是鼓励大家去计算一些中间统计结果,再计算出最终结果,为啥一定要一个函数解决所有问题啊。
    xlcoder166
        18
    xlcoder166  
       2019-12-25 19:57:12 +08:00
    题外话 我很好奇 在这种条件下能拿 A 的都是啥神仙啊 =.=
    smartG
        19
    smartG  
    OP
       2019-12-25 19:59:01 +08:00 via iPhone
    @passluo 多谢!看了大家的评论才发现我把问题复杂化了,我对 Excel 的函数功能了解不多,只知道 Python 可以处理批量数据,低估了 Excel 本身的强大功能
    smartG
        20
    smartG  
    OP
       2019-12-25 20:03:29 +08:00 via iPhone
    @xlcoder166 是每项单独的,百分制,不是最多降两级,有几项不及格就降几级,我看了一下,很少有超过两项不及格的
    DEANHZED
        21
    DEANHZED  
       2019-12-25 20:05:40 +08:00 via iPhone
    妹子国二没过吧?
    smartG
        22
    smartG  
    OP
       2019-12-25 20:05:54 +08:00 via iPhone
    @zeroDev 好的,我试一下!
    smartG
        23
    smartG  
    OP
       2019-12-25 20:06:15 +08:00 via iPhone
    @wangkun025 是的,用 Python 反而更复杂了
    smartG
        24
    smartG  
    OP
       2019-12-25 20:06:41 +08:00 via iPhone
    @zmxnv123 哈哈哈就是人事妹子
    smartG
        25
    smartG  
    OP
       2019-12-25 20:07:03 +08:00 via iPhone
    @zhy0216 i 好像有点问题……
    smartG
        26
    smartG  
    OP
       2019-12-25 20:07:53 +08:00 via iPhone
    @pzhzp 好的,明天上班试试,多谢啦
    smartG
        27
    smartG  
    OP
       2019-12-25 20:11:44 +08:00 via iPhone
    @DEANHZED 妹子用的 if,and 函数,多层嵌套……
    c6h6benzene
        28
    c6h6benzene  
       2019-12-25 20:14:08 +08:00 via iPhone
    我觉得 Excel 单独就能解决(但没有表格我也不知道在说什么
    lithiumii
        29
    lithiumii  
       2019-12-25 20:40:32 +08:00 via Android
    等级是不是不够?低于 60 也算 D ?还是算不及格?
    smartG
        30
    smartG  
    OP
       2019-12-25 21:08:55 +08:00 via iPhone
    @lithiumii 是啊,没写全,后面还有的
    daimiaopeng
        31
    daimiaopeng  
       2019-12-25 21:16:27 +08:00
    Excel 导出 csv 然后 python 操作 csv 简单一点
    jedicxl
        32
    jedicxl  
       2019-12-25 21:33:09 +08:00
    @xlcoder166 大型国企都这路数啊,我们公司就这么搞
    snw
        33
    snw  
       2019-12-25 22:15:00 +08:00 via Android
    这不就是多加几列算中间过程的事吗……
    yalin
        34
    yalin  
       2019-12-25 22:18:37 +08:00
    我也是用 pandas 各种弄
    sx90
        35
    sx90  
       2019-12-25 22:48:16 +08:00 via Android
    vba 了解一下
    lithiumii
        36
    lithiumii  
       2019-12-25 22:49:56 +08:00   ❤️ 1
    贴代码没有缩进,那干脆就一行一行来了,还能展示计算过程,其实 py 跟 excel 差不多,多加几步路就是了。

    import pandas as pd

    # 假定这个 excel 读进来就四列,n1, n2, n3, n4,每一行一个人
    df = pd.read_excel("C:/Users/acer/Desktop/绩效.xlsx")

    # 先数每个人挂了几科
    df["n_failed"] = df.apply(lambda x: sum(x < 60), axis=1)

    # 加权求和,反正权重是死的硬编码就是了
    df["sum"] = df["n1"] * 0.1 + df["n2"] * 0.2 + df["n3"] * 0.5 + df["n4"] * 0.2

    # 从 sum 得到用数字表示的等级( 5: A, 4: B, 3: C, 2: D, 小于 2 的不及格 F )
    df["raw_grade_int"] = df["sum"].apply(lambda x:int(x / 10) - 4)

    # 挂几科降几级
    df['final_grade_int'] = df["raw_grade_int"] - df['n_failed']

    # 从数字表示的等级转为 ABCDF,用个硬编码的字典对应
    df['final_grade']=df['final_grade_int'].apply(lambda x: {5: "A", 4: "B", 3: "C", 2: "D"}.get(x, 'F'))

    # 跳过不需要的列用于输出
    output_df = df[['n1', 'n2', 'n3', 'n4','final_grade']]

    # 输出,不需要 index
    output_df.to_excel("C:/Users/acer/Desktop/工具人.xlsx", index = False)
    AlphaTr
        37
    AlphaTr  
       2019-12-25 23:07:36 +08:00   ❤️ 1
    https://docs.qq.com/sheet/DR1J1Q1ltSGJ3ZWF1?c=F2A0A0 闲着贴一个 excel 出来;当然,可以将所有中间步骤函数合并到一起
    xiongdong57
        38
    xiongdong57  
       2019-12-25 23:08:14 +08:00   ❤️ 1
    def category(x):
    # column contains N1,N2,N3,N4,sum
    level = min(100 - x.loc['sum'], 30) // 10

    x = x[["N1", "N2", "N3", "N4"]]
    count = (x < 60).sum()
    category = level + min(count, 2)

    if category < 1:
    return "A"
    elif category < 2:
    return "B"
    elif category < 3:
    return "C"
    else:
    return "D"

    df['category'] = df.apply(category, axis=1)

    规则好像不全,可以全部补充到分类函数里
    Telegram
        39
    Telegram  
       2019-12-25 23:09:29 +08:00   ❤️ 1
    处理 EXCEL 当然是用自带的 VBA 最强大啊。
    https://i.loli.net/2019/12/25/524AsHLaoNiWTkY.png


    代码如下:

    Function JSS(rng As Range)
    Select Case rng(1) * 0.1 + rng(2) * 0.2 + rng(3) * 0.5 + rng(4) * 0.2

    Case 90 To 100
    sum1 = 65 'A ascii 码
    Case 80 To 89
    sum1 = 66 'B
    Case 70 To 79
    sum1 = 67 'C
    Case Is < 70
    sum1 = 68 'D
    End Select

    For i = 1 To 4
    If rng(i) < 60 Then sum2 = sum2 + 1 '统计小于 60 的个数
    If sum2 = 2 Then Exit For '两个项目小于 60,就别继续看了
    Next i

    JSS = Chr(sum1 + sum2)
    End Function


    具体使用方法:alt+F11,然后右键,插入,模块
    https://i.loli.net/2019/12/25/McivXKrDubyU59Y.png

    代码粘贴进去,然后就可以在表格里用这个函数了(函数一定要写在模块里)
    https://i.loli.net/2019/12/25/HLFiZkTRJlWVfw8.png
    x66
        40
    x66  
       2019-12-26 09:07:33 +08:00
    我有个朋友 excel 贼溜,想问一下在哪领妹子?
    smartG
        41
    smartG  
    OP
       2019-12-26 09:22:11 +08:00
    @Telegram 感谢大佬!我尝试一下用 VBA,越发感觉出来 Excel 的强大了
    @xiongdong57 好的,我试一下,感谢!
    @AlphaTr 按着您的做出来啦,感谢感谢!
    @lithiumii 是的,逻辑差不多,就是代码写不出来,向大佬学习啦,感谢!
    lework1234
        42
    lework1234  
       2019-12-26 13:17:50 +08:00
    office 套件没用好啊。
    kn007
        43
    kn007  
       2019-12-26 19:56:27 +08:00
    过来 mark 一下
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1052 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 22:36 · PVG 06:36 · LAX 14:36 · JFK 17:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.