如何从熊猫数据框中的列表列中的列表中随机选择

时间:2020-02-17 19:11:36

标签: python pandas

我有以下数据框:

MyAge    Ages       Names
7       [3,10,15]   ['Tom','Jack','Sara']
6       [12,6,5,13] ['Nora','Betsy','John','Jill']
15      [24,3,65,15]['Tala','Jane','Bill','Mark']

我想生成一个新列,为Names列表中的每一行生成一个随机选择的名称,以使具有该随机选择名称的人的年龄小于或等于{{1 }}。 MyAge列反映了Ages列中每个人的年龄。

因此可能的结果如下:

Names

1 个答案:

答案 0 :(得分:1)

鉴于每行的年龄和名称的数目可以不同,请首先使用列表推导基于每行的年龄/名称的数目创建一个随机索引。然后使用更多列表推导为名称和年龄建立索引。最后,将结果分配回原始数据框。

# Sample data.
df = pd.DataFrame({
    "MyAge": [7, 6, 15],
    "Ages": [[3, 10, 15], [12, 6, 5, 13], [24, 3, 65, 15]],
    "Names": [['Tom', 'Jack', 'Sara'], ['Nora', 'Betsy', 'John', 'Jill'], ['Tala', 'Jane', 'Bill', 'Mark']]
})

# Solution.
np.random.seed(0)
random_index = [np.random.randint(len(ages)) for ages in df['Ages']]
names = [names[idx] for idx, names in zip(random_index, df['Names'])]
ages = [ages[idx] for idx, ages in zip(random_index, df['Ages'])]
>>> df.assign(RandomName=names, RandomPersonAge=ages)
    MyAge   Ages        Names                     RandomName    RandomPersonAge
0   7   [3, 10, 15]     [Tom, Jack, Sara]         Tom            3
1   6   [12, 6, 5, 13]  [Nora, Betsy, John, Jill] Jill          13
2   15  [24, 3, 65, 15] [Tala, Jane, Bill, Mark]  Jane           3

要选择随机年龄以使其小于或等于MyAge中的值,我们应该首先将数据展平。我们将使用条件嵌套列表理解来过滤数据,以便每一行都包含索引以及名称和等效年龄,其中年龄小于或等于MyAge。然后,我们将从过滤后的数据中创建一个数据框,并根据第一列(即原始数据框索引的名称)设置索引。数据帧中的行通过sample(frac=1)随机进行了混洗。然后,我们对索引进行分组并取得第一条随机行。然后,我们将结果连接回原始数据帧(默认情况下,连接是根据索引完成的。)

filtered_data = (
    [(idx, name, age) 
     for idx, (my_age, ages, names) in df.iterrows() 
     for age, name in zip(ages, names)
     if age <= my_age]
)
random_names_and_ages = (
    pd.DataFrame(filtered_data, columns=[df.index.name, 'RandomName', 'RandomPersonAge'])
    .set_index(df.index.name)
    .sample(frac=1)  # Randomly huffle the rows in the dataframe.
    .groupby(level=0)[['RandomName', 'RandomPersonAge']]  # Groupby 'ID' and take the first random row.
    .first()
)
>>> df.join(random_names_and_ages)
   MyAge             Ages                      Names RandomName  \
0      7      [3, 10, 15]          [Tom, Jack, Sara]        Tom   
1      6   [12, 6, 5, 13]  [Nora, Betsy, John, Jill]       John   
2     15  [24, 3, 65, 15]   [Tala, Jane, Bill, Mark]       Jane   

   RandomPersonAge  
0                3  
1                5  
2                3