从模型创建数据框
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
解释:
- 首先
groupby
id, breed_name 列并将结果汇总为 list
.
- 然后找到
max
没有。需要 value 列,并将聚合列表值转换为
featurevalue__feature_value 列使用 pandas.Series
. 分隔 value 列
- 最后删除 featurevalue__feature_value 列。
我正在使用 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
解释:
- 首先
groupby
id, breed_name 列并将结果汇总为list
. - 然后找到
max
没有。需要 value 列,并将聚合列表值转换为 featurevalue__feature_value 列使用pandas.Series
. 分隔 value 列
- 最后删除 featurevalue__feature_value 列。