如何根据特定分布将DataFrame观察值分配给组?

时间:2018-02-14 16:51:10

标签: python pandas dataframe

我有一个pandas DataFrame,其中每个观察(行)代表一个人。

我想将满足特定条件的每个人分配到不同的组。我需要这个,因为我的最终目标是创建一个网络,并将同一组中的人与一些依赖于该组的概率联系起来。

所以,例如,我想把所有6到10岁的孩子分配给学校。最后,我将在同一所学校的孩子之间建立一个特定概率 p 的链接。

我知道我想要模拟的区域的学校的大小分布。 所以我想从这个发行版中画出学校规模,然后“填写”#34;所有6至10岁儿童的学校。

我是熊猫新手:我想要这样做的方法是创建一个新列,用NaN填充,然后只为不同的学生分配一个学校ID。

我们说我的DataFrame df就是这样:

import pandas as pd
import numpy as np

df = pd.DataFrame({'ID': range(11), 'AGE': [15, 6, 54, 8, 10, 39, 2, 7, 9, 10, 6]})

df
Out[1]: 
    AGE  ID
0    15   0
1     6   1
2    54   2
3     8   3
4    10   4
5    39   5
6     2   6
7     7   7
8     9   8
9    10   9
10    6  10

(顺便说一句,我不知道如何将ID列放在第一位,但无论如何在现实生活中我都是从CSV文件中读取数据帧,这样就没有问题了。 / p>

现在,我想要做的是创建另一个专栏ELEM_SCHOOL_ID,将其初始化为NaN,然后只为正确年龄的人分配值。

我到目前为止所取得的成就是:与满足年龄条件的人一起创建DataFrame的子集。

df['IN_ELEM_SCH'] = np.where((df['AGE']>5) & (df['AGE']<11), 'True', 'False')
df
Out[2]: 
    AGE  ID IN_ELEM_SCH
0    15   0       False
1     6   1        True
2    54   2       False
3     8   3        True
4    10   4        True
5    39   5       False
6     2   6       False
7     7   7        True
8     9   8        True
9    10   9        True
10    6  10        True

然后,我需要添加另一列ELEM_SCHOOL_ID,其中包含每个学生参加的特定小学的ID。

我可以使用以下命令初始化新列:

df["ELEM_SCHOOL_ID"] = np.nan
df
Out[84]: 
    AGE  ID IN_ELEM_SCH  SCHOOL_ID
0    15   0       False        NaN
1     6   1        True        NaN
2    54   2       False        NaN
3     8   3        True        NaN
4    10   4        True        NaN
5    39   5       False        NaN
6     2   6       False        NaN
7     7   7        True        NaN
8     9   8        True        NaN
9    10   9        True        NaN
10    6  10        True        NaN

我现在想做的是:

  1. 从学校规模分布中抽取一个数字: n0
  2. 对于满足年龄条件的 n0 随机人员(那些有IN_ELEM_SCHOOL == True的人),将0分配给SCHOOL_ID
  3. 从学校规模分布中抽取另一个数字: n1
  4. 对于仍未分配到学校的 n1 随机人员,请将1分配给SCHOOL_ID
  5. 重复,直到所有IN_ELEM_SCH == True的人都被分配了学校ID。
  6. 因此,举例来说,让我们说从分布中抽取的第一个学校规模为n0=2,第二个n1=3和第三个n2=4。 我想最终得到这样的东西:

        AGE  ID IN_ELEM_SCH  SCHOOL_ID
    0    15   0       False        NaN
    1     6   1        True        0
    2    54   2       False        NaN
    3     8   3        True        1
    4    10   4        True        2
    5    39   5       False        NaN
    6     2   6       False        NaN
    7     7   7        True        1
    8     9   8        True        1
    9    10   9        True        2
    10    6  10        True        0
    

    在现实生活中,学校规模分布为对数正态分布。比如,参数mu = 4sigma = 1 然后我可以从这个分布中得出:

    s = np.random.lognormal(mu, sigma, 100)
    

    但我仍然无法弄清楚如何分配学校。

    我为这个问题的篇幅道歉,但我想说清楚。

    非常感谢你给我的任何暗示或帮助。

1 个答案:

答案 0 :(得分:1)

在分配新数据时,Pandas会自动匹配索引。结帐大熊猫docs on indexing

注意:您通常不会创建额外的IN_ELEM_SCHOOL列(即下面代码中的第三行是不必要的)。

mu, sigma = 1, 0.5

m = (5 < df['AGE']) & (df['AGE'] < 11)
df['IN_ELEM_SCHOOL'] = m

s = m[m].sample(frac=1)

n, i = 0, 0
while n < len(s):
    num_students = int(np.random.lognormal(mu, sigma))
    s[n: n + num_students] = i
    i += 1
    n += num_students
df['SCHOOL_ID'] = s
df

返回

    AGE  ID  IN_ELEM_SCHOOL  SCHOOL_ID
0    15   0           False        NaN
1     6   1            True        0.0
2    54   2           False        NaN
3     8   3            True        1.0
4    10   4            True        2.0
5    39   5           False        NaN
6     2   6           False        NaN
7     7   7            True        1.0
8     9   8            True        0.0
9    10   9            True        0.0
10    6  10            True        1.0