从模型中创建数据帧



我正在使用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"one_answers"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

我该怎么修?

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

您可以枚举每组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. 第一个groupbyid,breed_name列,并将结果聚合为list
  2. 然后找到所需的max列,并将聚合列表值转换为featurevalue__feature_value列以使用pandas.Series分隔的列
  3. 最后删除featurevalue__feature_value

最新更新