基于列和行列表重构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 有效地做到这一点,尤其是因为您的数据中有重复项并且简单的数据透视会失败(您似乎保留了第一个值,尽管不完全确定,请澄清这一点)。

此外,您的输出看起来像是一个数据框,那么为什么不直接将pandaspivot_tableaggfunc='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 数组?

每次执行代码时,Numpy 2-D 数组都会更改值

基于形状的 numpy 数组的分组列表。熊猫?

Python - 如何创建一个空的numpy数组并附加到它,如列表[重复]

包含具有可变形状的多维 numpy 数组的 numpy 数组

Python numpy 多维数组由另一个数组值过滤