我有一个JSON格式的表(字典列表),其中每一行都是一个字典。
为简单起见,我要这样一行:
{
'dimension1': 'foo',
'dimension2': 'bar',
'metric1': 102,
'metric2': 200
}
我想知道是否有一种简单的方法(也许使用熊猫或其他任何python工具)将该行拆分为给定数量的n
行,其中:
int
,应保留为int
。例如,如果为n = 4
,则上一行的输出应为:
[{
'dimension1': 'foo',
'dimension2': 'bar',
'metric1': 25,
'metric2': 50
},{
'dimension1': 'foo',
'dimension2': 'bar',
'metric1': 25,
'metric2': 50
},{
'dimension1': 'foo',
'dimension2': 'bar',
'metric1': 26,
'metric2': 50
},{
'dimension1': 'foo',
'dimension2': 'bar',
'metric1': 26,
'metric2': 50
}]
我试图寻找一种使用pandas
或其他工具进行此操作的方法,但是找不到一种方法来给出一组应保持静态的维度和一组应拆分的指标同时保持总和。
希望这很清楚。我知道可以明确地编写此逻辑,但想知道是否有我缺少的更简单,更强大的方法。
答案 0 :(得分:1)
可能不是最干净的一种,但可以使用np.histrogram
将值转换为bins来尝试
def value_to_bins(df_value,n):
value=np.arange(df_value, dtype=int)
return np.histogram(value, bins=n)[0]
import pandas as pd
import numpy as np
d={
'dimension1': 'foo',
'dimension2': 'bar',
'metric1': 101,
'metric2': 200
}
df=pd.DataFrame(d,index=[0])
n=2
df2=pd.DataFrame(index=range(n),columns=['dimension1','dimension2']) # create new dataframe with NaN
df2.dimension1=df2.dimension1.fillna(df.dimension1[0]) # fill with values of previous dimension1
df2.dimension2=df2.dimension2.fillna(df.dimension2[0]) # fill with values of previous dimension2
df2['metric1'] = value_to_bins(df.metric1[0],n)
df2['metric2'] = value_to_bins(df.metric2[0],n)
df2.to_dict('records')
输出
[{'dimension1': 'foo', 'dimension2': 'bar', 'metric1': 50L, 'metric2': 100L},
{'dimension1': 'foo', 'dimension2': 'bar', 'metric1': 51L, 'metric2': 100L}]
要保留int
值
[{k:int(v) if v!=np.nan and k in ['metric1','metric2'] else v for k,v in i.items() } for i in df2.to_dict('records')]
输出
[{'dimension1': 'foo', 'dimension2': 'bar', 'metric1': 50, 'metric2': 100},
{'dimension1': 'foo', 'dimension2': 'bar', 'metric1': 51, 'metric2': 100}]
答案 1 :(得分:0)
您可以使用下层和列表理解以及字典理解:
想法是计算层,然后将每个元素的提醒除以1并共享,以使每个元素尽可能接近,例如假设102
和n=4
我们有reminder=2
,则结果为:{ {1}}
25+1,25+1,25,25
输出(n = 4):
import math
data={
'dimension1': 'foo',
'dimension2': 'bar',
'metric1': 102,
'metric2': 203
}
#finds all keys with integer values
division_fields=[k for k,v in data.items() if str(v).isdigit()]
values={}
n=4
#creates a list with desired values for each numeric field
#and diveds reminder betweens elements of list by 1 foreach element
for field in division_fields:
values[field]= [math.floor(data[field]/n) if i+1>data[field]%n else math.floor(data[field]/n)+1 for i in range(0,n)]
result=[{k:values[k][i] if k in division_fields else v for k,v in data.items() } for i in range(0,n)]
print (result)