【问题标题】:Create a dataframe from the model从模型创建数据框
【发布时间】:2021-06-05 17:28:26
【问题描述】:

我正在使用 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')

在“特征”模型中,我有 3 条带有 feature_code 的记录,其值例如为“value1”、“value2”、“value3”。在“品种”模型中,我还有 3 条记录,每条记录都为“特征”模型中的每条记录分配了值(我使用 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

我该如何解决?

【问题讨论】:

    标签: python django pandas dataframe model


    【解决方案1】:

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

    您可以枚举每组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
    

    【讨论】:

      【解决方案2】:

      你可以这样做:

      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 分隔 value 列。
      3. 最后删除 featurevalue__feature_value 列。

      【讨论】:

        猜你喜欢
        • 2023-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-10
        • 2018-07-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多