熊猫-Groupby小计百分比

时间:2020-01-30 12:03:34

标签: pandas pandas-groupby

我有一个DF,我想按两列进行分组。我想显示的是level = 1中每个项目(例如“ c”)在level = 0中每个项目的总和的百分比(在下面的示例中,即“ a”和“ b”的总和)的百分比,在示例中为“ d”,“ e”)。

示例:

我有以下数据框

def ineffectiveScale(self):
    ws = Window.size
    part = 600
    whole = ws[1]
    dif = whole-part
    percent = 100 * float(dif)/float(whole)
    if ws[1] <= 1000:
        self.size = 0.7+(percent * 0.8) / 100.0
    elif ws[1] >= 1000 and ws[1] <= 2000:
        self.size = 1.1+(percent * 1.2) / 100.0
    elif ws[1] >= 2000 and ws[1] <= 3000:
        self.size = 1.6+(percent * 1.7) / 100.0
    elif ws[1] >= 3000 and ws[1] <= 4000:
        self.size = 2.0+(percent * 2.1) / 100.0
    elif ws[1] >= 4000:
        self.size = 2.5+(percent * 2.6) / 100.0

我想获得这个:

from __future__ import division
from collections import namedtuple
import json
import math
import random
from kivy import platform
from kivy.app import App
from kivy.base import EventLoop
from kivy.clock import Clock
from kivy.core.image import Image
from kivy.core.window import Window
from kivy.graphics import Mesh
from kivy.graphics.instructions import RenderContext
from kivy.uix.widget import Widget
from kivy.utils import get_color_from_hex
import base64

UVMapping = namedtuple('UVMapping', 'u0 v0 u1 v1 su sv')

GLSL = """
---vertex
$HEADER$

attribute vec2  vCenter;
attribute float vScale;

void main(void)
{
    tex_coord0 = vTexCoords0;
    mat4 move_mat = mat4
        (1.0, 0.0, 0.0, vCenter.x,
         0.0, 1.0, 0.0, vCenter.y,
         0.0, 0.0, 1.0, 0.0,
         0.0, 0.0, 0.0, 1.0);
    vec4 pos = vec4(vPosition.xy * vScale, 0.0, 1.0)
        * move_mat;
    gl_Position = projection_mat * modelview_mat * pos;
}

---fragment
$HEADER$

void main(void)
{
    gl_FragColor = texture2D(texture0, tex_coord0);
}

"""

with open("game.glsl", "w")  as wr:
    wr.write(GLSL)

def load_atlas():
    atlas = json.loads('''{"img.png": {"Elien": [2, 26, 100, 100]}}''')
    tex_name, mapping = atlas.popitem()
    data = '''iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAACJklEQVR4nO3dy1ICQRAF0YLw/39ZVxMBGCjEMF23JvOsXPgounMaN61VQrtsH3x3TqFfLv9/ykdcq9z8RKv25Lro5yiUAcAZAJwBwBkAnAHAGQCcAcAZAJwBwBkAnAHAGQCcAcAZAJwBwBkAnAHAGQCcAcAZAJwBwBkAnAHAfXUPsNM79ydWXbYZZVoAey7MPH6tQdScAI64KbV9T3QI6QGsuCKHDiH5l8DVd1aRd2QTT4DOjcCdBmknQMpTmDLH4ZICSFv0tHkOkRJA6mKnzvUxCQGkL3L6fLskBKBG3QFMebqmzPm2zgCmLeq0eV/SfQKoWVcAU5+mqXM/5QkA1xHA9Kdo+vx3PAHgDADOAOBWB3CW98+zvA5PADoDgDMAOAOAMwA4A4AzADgDgDMAuNUBnOXCxVlehycAnQHAGQBcRwDT3z+nz3/HEwCuK4CpT9HUuZ/yBIDrDGDa0zRt3pd0nwBTFnXKnG/rDkDNEgJIf7rS59slIYCq3EVOnetjUgKoylvstHkOkRRAVc6ip8xxuMS/E7gtfsflC8zGb9JOgFurNwO3+VWZJ8CtFacBcuM36QFsjggBvfGbKQFsHjfNfxix07QAHrmpOyX/EqgFDADOAOAMAM4A4AwAzgDgDADOAOAMAM4A4AwAzgDgDADOAOAMAM4A4AwAzgDgDADOAOAMAM4A4AwA7lrl7YpE7okkSZIkSZIkSZIkSZIkSZIkSZL+9AMvSSThyPfOhQAAAABJRU5ErkJggg=='''
    with open(tex_name, "wb")  as co:
        co.write(base64.b64decode(data))
    tex = Image(tex_name).texture
    tex_width, tex_height = tex.size

    uvmap = {}
    for name, val in mapping.items():
        x0, y0, w, h = val
        x1, y1 = x0 + w, y0 + h
        uvmap[name] = UVMapping(
            x0 / tex_width, 1 - y1 / tex_height,
            x1 / tex_width, 1 - y0 / tex_height,
            0.5 * w, 0.5 * h)

    return tex, uvmap


class Particle:
    x = 0
    y = 0
    size = 1

    def __init__(self, parent, i):
        self.parent = parent
        self.vsize = parent.vsize
        self.base_i = 4 * i * self.vsize
        self.reset(created=True)

    def update(self):
        for i in range(self.base_i,
                       self.base_i + 4 * self.vsize,
                       self.vsize):
            self.parent.vertices[i:i + 3] = (
                self.x, self.y, self.size)

    def reset(self, created=False):
        raise NotImplementedError()

    def advance(self, nap):
        raise NotImplementedError()


class GameScreen(Widget):
    indices = []
    vertices = []
    particles = []

    def __init__(self, **kwargs):
        Widget.__init__(self, **kwargs)
        self.canvas = RenderContext(use_parent_projection=True)
        self.canvas.shader.source = "game.glsl"

        self.vfmt = (
            (b'vCenter', 2, 'float'),
            (b'vScale', 1, 'float'),
            (b'vPosition', 2, 'float'),
            (b'vTexCoords0', 2, 'float'),
        )

        self.vsize = sum(attr[1] for attr in self.vfmt)
        self.texture, self.uvmap = load_atlas()

    def make_particles(self, Ap, num):
        count = len(self.particles)
        uv = self.uvmap[Ap.tex_name]

        for i in range(count, count + num):
            j = 4 * i
            self.indices.extend((
                j, j + 1, j + 2, j + 2, j + 3, j))

            self.vertices.extend((
                0, 0, 1, -uv.su, -uv.sv, uv.u0, uv.v1,
                0, 0, 1,  uv.su, -uv.sv, uv.u1, uv.v1,
                0, 0, 1,  uv.su,  uv.sv, uv.u1, uv.v0,
                0, 0, 1, -uv.su,  uv.sv, uv.u0, uv.v0,
            ))

            p = Ap(self, i)
            self.particles.append(p)

    def update_glsl(self, nap):
        for p in self.particles:
            p.advance(nap)
            p.update()

        self.canvas.clear()

        with self.canvas:
            Mesh(fmt=self.vfmt, mode='triangles',
                 indices=self.indices, vertices=self.vertices,
                 texture=self.texture)

class ScaleTest(Particle):
    tex_name = 'Elien' 
    texture_size = 129

    def reset(self, created=False):
        self.x = random.randint(15, self.parent.right-15)
        self.y = random.uniform(-100, -2500)
        self.size = 1 #FULL SIZE BEFORE RESIZED
        self.ineffectiveScale() #Comment this line to see the problem of large resolution screens

    def ineffectiveScale(self):
        ws = Window.size
        part = 600
        whole = ws[1]
        dif = whole-part
        percent = 100 * float(dif)/float(whole)
        if ws[1] <= 1000:
            self.size = 0.7+(percent * 0.8) / 100.0
        elif ws[1] >= 1000 and ws[1] <= 2000:
            self.size = 1.1+(percent * 1.2) / 100.0
        elif ws[1] >= 2000 and ws[1] <= 3000:
            self.size = 1.6+(percent * 1.7) / 100.0
        elif ws[1] >= 3000 and ws[1] <= 4000:
            self.size = 2.0+(percent * 2.1) / 100.0
        elif ws[1] >= 4000:
            self.size = 2.5+(percent * 2.6) / 100.0

    def advance(self, nap):
        self.y += 100 * 2 * nap
        if self.y > self.parent.top:
            self.reset()

class Game(GameScreen):
    def initialize(self):
        self.make_particles(ScaleTest, 20)

    def update_glsl(self, nap):
        GameScreen.update_glsl(self, nap)

class GameApp(App):
    def build(self):
        EventLoop.ensure_window()
        return Game()

    def on_start(self):
        self.root.initialize()
        Clock.schedule_interval(self.root.update_glsl, 60 ** -1)

if __name__ == '__main__':
    Window.clearcolor = get_color_from_hex('111110')
    GameApp().run()

1 个答案:

答案 0 :(得分:3)

首先将sum按两列进行汇总,然后按sum的第一级除以DataFrame.div MultiIndex

df1 = df.groupby(['col1','col2']).sum()
df1 = df1.div(df1.sum(level=0), level=0)
print (df1)
           col3
col1 col2      
a    c      0.4
     d      0.4
     e      0.2
b    c      0.4
     d      0.4
     e      0.2