从模型创建数据框

Create a dataframe from the model

我正在使用 Django 编写应用程序,我 运行 遇到了问题。我的模型如下:

class Feature(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    feature_name = models.CharField(max_length=300)
    feature_code = models.CharField(max_length=50, unique=True)
    feature_predictable = models.BooleanField(default=False)

    def __str__(self):
        return self.feature_name


def breed_name_based_upload_to(instance, filename):
    return "breeds/{0}/{1}".format(instance.breed_name, filename)


class Breed(models.Model):
    breed_name = models.CharField(max_length=300)
    breed_features = models.ManyToManyField(Feature)
    breed_image = models.ImageField(default='no_image.png', upload_to=breed_name_based_upload_to)
    breed_visible = models.BooleanField(default=True)

    def __str__(self):
        return self.breed_name


class FeatureValue(models.Model):
    breed = models.ForeignKey(Breed, on_delete=models.CASCADE)
    feature = models.ForeignKey(Feature, on_delete=models.CASCADE)
    feature_value = IntegerRangeField(min_value=1, max_value=3, default=1)

    class Meta:
        unique_together = ('breed', 'feature')

在 'Feature' 模型中,我有 3 条 feature_code 的记录,其值例如 'value1'、'value2'、'value3'。在 'Breed' 模型中,我也有 3 条记录,这些记录中的每条记录都为 'Feature' 模型中的每条记录分配了值(我使用 FeatureValue 模型分配值)。

现在我需要使用 Breed 模型创建一个如下所示的 DataFrame:

id   breed_name  value1   value2   value3
 0        name1       2        1        3
 1        name2       1        2        2
 2        name3       3        3        3

目前,使用此代码:

dataframe = pandas.DataFrame().from_records(list(
    Breed.objects.all().values(
        'id',
        'breed_name',
        'featurevalue__feature_value'
    )
))

我设法实现了这样的目标:

id   breed_name   featurevalue__feature_value
 0        name1                             2
 0        name1                             1
 0        name1                             3
 1        name2                             1
 1        name2                             2
 1        name2                             2
 2        name3                             3
 2        name3                             3
 2        name3                             3

我该如何解决?

如果我们从您的示例数据框开始。

您可以枚举每组 breed_name 个值中的行。

>>> df["pos"] = df.groupby("breed_name").cumcount()
>>> df["pos"] = "value" + df["pos"].astype("str")
>>> df
   id breed_name  featurevalue__feature_value     pos
0   0      name1                            2  value0
1   0      name1                            1  value1
2   0      name1                            3  value2
3   1      name2                            1  value0
4   1      name2                            2  value1
5   1      name2                            2  value2
6   2      name3                            3  value0
7   2      name3                            3  value1
8   2      name3                            3  value2

然后旋转数据框,删除额外级别的列索引并重置行索引。

>>> df2 = df.pivot(columns="pos", index=["id", "breed_name"])
>>> df2
              featurevalue__feature_value
pos                                value0 value1 value2
id breed_name
0  name1                                2      1      3
1  name2                                1      2      2
2  name3                                3      3      3

>>> df2 = df2.droplevel(0, axis=1).reset_index()
>>> df2
pos  id breed_name  value0  value1  value2
0     0      name1       2       1       3
1     1      name2       1       2       2
2     2      name3       3       3       3

您可以按照以下方式进行:

df2 = df.groupby(['id','breed_name'], as_index=False).agg(list)

max_values = df2.featurevalue__feature_value.str.len().max()
df2[['value'+str(i+1) for i in range(max_values)]] = df2.featurevalue__feature_value.apply(pd.Series)

df2.drop('featurevalue__feature_value', axis=1, inplace=True)
输出:
>>> df2
   id breed_name  value1  value2  value3
0   0      name1       2       1       3
1   1      name2       1       2       2
2   2      name3       3       3       3

解释:

  1. 首先 groupby id, breed_name 列并将结果汇​​总为 list.
  2. 然后找到max没有。需要 value 列,并将聚合列表值转换为 featurevalue__feature_value 列使用 pandas.Series.
  3. 分隔 value
  4. 最后删除 featurevalue__feature_value 列。