基于列和行列表重构numpy数组(如numpy数组中的数据透视表)
Posted
技术标签:
【中文标题】基于列和行列表重构numpy数组(如numpy数组中的数据透视表)【英文标题】:Restructure numpy array based on column and row list (Like pivot table in numpy array) 【发布时间】:2022-01-09 20:03:23 【问题描述】:这里是示例 numpy 数据源
col row1 row2 row3 row4 columns
[[( 11.2, '689', '197', 'value_2', 0, 1)]
[( 56.4, '689', '197', 'value_3', 0, 1)]
[( 195.7, '689', '197', 'value_2', 0, 2)]
[( 565.2, '689', '197', 'value_3', 0, 2)]
[( 227.6, '689', '197', 'value_2', 0, 3)]
[( 1347.6, '689', '197', 'value_2', 0, 3)]
[( 613.5, '689', '196', 'value_2', 0, 1)]
[(139. , '689', '196', 'value_3', 0, 1)]
[( 6011. , '689', '196', 'value_2', 0, 2)]
[(103. , '689', '196', 'value_3', 0, 2)]
[( 6860. , '689', '196', 'value_2', 0, 3)]
[(1302. , '689', '196', 'value_3', 0, 3)]
[( 1787.9, '622', '197', 'value_2', 0, 1)]
[( 632.5, '622', '197', 'value_3', 0, 1)]
[( 178.8, '622', '197', 'value_2', 0, 2)]
[( 6360.5, '622', '197', 'value_3', 0, 2)]
[( 228. , '622', '196', 'value_2', 0, 1)]
[(672. , '622', '196', 'value_3', 0, 2)]
]
所以从这个预期的输出应该是
1 2 3
row1 row2 row3 row4
689 197 value_2 0 11.2 195.7 227.6
689 197 value_3 0 56.4 565 1347
689 196 value_2 0 613.5 6011 6860
689 196 value_3 0 139 103 1302
622 197 value_2 0 1787 178
622 197 value_3 0 632 6360
超过 1 2 3 列是从 numpy 数组中的一列得到的,即排名
从给定的数据来看,row1 永远是 1,但它有多个 row2、row3 和 row4。 对于 row1 中的每个数据,都应该找到等效的行并按照输出中的说明进行填充。
我尝试了下面的代码,但无法正确获取 (1, 2, 3) 列值,因为它位于不同的位置,我无法在 numpy 数组中写入。
new_temp_arr = 'actual_data_given'
m = 1
row_list = ['row1', 'row2', 'row3', 'row4']
# Column list taken from the array based on rank column
column_list = [1, 2, 3]
sample_list = []
for value in new_temp_arr:
for new_value in new_temp_arr:
if m >= len(new_temp_arr):
break
new_value = new_temp_arr[m]
# Checking all the values for the rows matches with one another
condition = [value[row] == new_value[row] for row in row_list]
if all(condition):
# Looping through all the column list and getting the float value
# I'm stuck here, how to store the values with properly matched data
for per in column_list:
if new_value['rank'] == [per]:
float_value = new_value['float_value']
sample_list.append(new_value)
m += 1
【问题讨论】:
“示例 numpy 数据源”的性质尚不清楚。列标题不是数组的一部分。[]
和 ()
的嵌套表明它是一个结构化数组,但您没有提供 shape 或 dtype。但它可能是对象 dtype,或者只是元组列表。我不认为numpy
在这里会有所帮助。对于分组操作,我喜欢使用dict
,甚至collections.defaultdict
。
是的,它是一个结构化数组,我提到的 dtype 为 col 行等。感谢您的输入,我尝试使用 defaultdict
你知道完整的唯一row#
值吗?
唯一行,意思是,你到底在问什么?
【参考方案1】:
我认为您不能使用 numpy
有效地做到这一点,尤其是因为您的数据中有重复项并且简单的数据透视会失败(您似乎保留了第一个值,尽管不完全确定,请澄清这一点)。
此外,您的输出看起来像是一个数据框,那么为什么不直接将pandas
与pivot_table
和aggfunc='first'
一起使用呢?:
a = np.array([[( 11.2, '689', '197', 'value_2', 0, 1)],
[( 56.4, '689', '197', 'value_3', 0, 1)],
[( 195.7, '689', '197', 'value_2', 0, 2)],
[( 565.2, '689', '197', 'value_3', 0, 2)],
[( 227.6, '689', '197', 'value_2', 0, 3)],
[( 1347.6, '689', '197', 'value_2', 0, 3)],
[( 613.5, '689', '196', 'value_2', 0, 1)],
[(139. , '689', '196', 'value_3', 0, 1)],
[( 6011. , '689', '196', 'value_2', 0, 2)],
[(103. , '689', '196', 'value_3', 0, 2)],
[( 6860. , '689', '196', 'value_2', 0, 3)],
[(1302. , '689', '196', 'value_3', 0, 3)],
[( 1787.9, '622', '197', 'value_2', 0, 1)],
[( 632.5, '622', '197', 'value_3', 0, 1)],
[( 178.8, '622', '197', 'value_2', 0, 2)],
[( 6360.5, '622', '197', 'value_3', 0, 2)],
[( 228. , '622', '196', 'value_2', 0, 1)],
[(672. , '622', '196', 'value_3', 0, 2)],
])
cols = ['col', 'row1', 'row2', 'row3', 'row4', 'columns']
(pd.DataFrame(a[:,0,:], columns=cols)
.pivot_table(index=['row1', 'row2', 'row3', 'row4'], columns='columns', values='col', aggfunc='first')
)
输出:
columns 1 2 3
row1 row2 row3 row4
622 196 value_2 0 228.0 NaN NaN
value_3 0 NaN 672.0 NaN
197 value_2 0 1787.9 178.8 NaN
value_3 0 632.5 6360.5 NaN
689 196 value_2 0 613.5 6011.0 6860.0
value_3 0 139.0 103.0 1302.0
197 value_2 0 11.2 195.7 227.6
value_3 0 56.4 565.2 NaN
如果订单很重要,您可以reindex
原始订单:
cols = ['col', 'row1', 'row2', 'row3', 'row4', 'columns']
df = pd.DataFrame(a[:,0,:], columns=cols)
idx = df.set_index(['row1', 'row2', 'row3', 'row4']).index
idx = idx[~idx.duplicated(keep='first')]
(df.pivot_table(index=['row1', 'row2', 'row3', 'row4'], columns='columns', values='col', aggfunc='first')
.reindex(idx)
)
输出:
columns 1 2 3
row1 row2 row3 row4
689 197 value_2 0 11.2 195.7 227.6
value_3 0 56.4 565.2 NaN
196 value_2 0 613.5 6011.0 6860.0
value_3 0 139.0 103.0 1302.0
622 197 value_2 0 1787.9 178.8 NaN
value_3 0 632.5 6360.5 NaN
196 value_2 0 228.0 NaN NaN
value_3 0 NaN 672.0 NaN
【讨论】:
我必须只使用 numpy,这是要求。订单不是问题。任何值都可以排在第一位,这不是问题。我只需要用 numpy 提取这个结构。【参考方案2】:def get_list(arr, row1, row_column_values, row_list, column_list, index):
dict_keys = i: [] for i in column_list
dic = row1: dict_keys
for value in arr:
if index == len(arr):
index = 0
value = arr[index]
condition = [value[row][0] == row_column_values[row] for row in row_list]
if all(condition):
dic[row1][int(value['rank'][0])] = value['float_value'][0]
if index == 0:
break
index += 1
new_temp_arr = 'actual_data_given'
m = 1
row_list = ['row1', 'row2', 'row3', 'row4']
# Column list taken from the array based on rank column
column_list = [1, 2, 3]
out_array = np.zeros() #Numpy array with type
dic =
for value in new_temp_arr:
row_values = row: value[row][0] for row in row_list
dic = get_list(new_temp_arr, value['row1'][0], row_values, row_list, column_list, m)
float_value = list(dic[value['row1'][0]].values())
out_array[out_index] = tuple(list(value[row_list][0]) + float_value)
return out_array
上面的代码得到了我在问题中提到的预期结果。
【讨论】:
以上是关于基于列和行列表重构numpy数组(如numpy数组中的数据透视表)的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Pandas DataFrame 的列和行子集转换为 numpy 数组?
Python - 如何创建一个空的numpy数组并附加到它,如列表[重复]