融化包含字典列的熊猫数据框,以使字典值也融化

时间:2020-04-21 22:42:47

标签: python pandas merge data-manipulation

这不是重复的

此问题:Pandas column dict split to new column and rows没有回答本文中的问题。在本文的结尾,我提供了一种将字典的列转换为数据框的方法,这并不是我在这里遇到的困难。


设置

给出以下数据:

d1 = {'a' : 12, 'b' : 44}
d2 = {'this' : 9, 'that' : 33, 'there' : 82}
d3 = {'x' : 19, 'y' : 38, 'z' : 12, 't' : 90}
df = pd.DataFrame(dict(
    var_1 = [1,2,3],
    var_2 = ['one', 'two', 'four'],
    var_3 = [d1, d2, d3]
))

外观如下:

   var_1 var_2                                 var_3
0      1   one                    {'a': 12, 'b': 44}
1      2   two  {'this': 9, 'that': 33, 'there': 82}
2      3  four  {'x': 19, 'y': 38, 'z': 12, 't': 90}

我希望能够.melt,特别是id_vars,以一种 还从var_3列中提取了字典。

仅在第一行中使用

   var_1 var_2                                 var_3
0      1   one                    {'a': 12, 'b': 44}

预期的中期结果将是:

   var_1 var_2   key   value    
0      1   one    a     12
1      1   one    b     44

融化后将是:

# using df.melt(id_vars = ['var_1', 'var_2'])

   var_1 var_2 variable value
0      1   one      key     a
1      1   one      key     b
2      1   one    value    12
3      1   one    value    44

我想对所有数据执行此操作。

尝试

说实话,我不确定该怎么做。

# make key : value dataframe
row_i = 0
col_i = 2
key_value_df = (pd.DataFrame( df.iloc[ row_i, col_i], index= [0 ]  )
                    .T.reset_index()
                    .rename(columns = {'index' : 'key', 0 : 'value'})
            )

data_thing = (pd.concat( [pd.DataFrame(df.iloc[ 0 , [0,1]]
                    .to_dict(), index=[0])] * len(key_value_df) ))

然后

data_thing.join(key_value_df).reset_index(drop=True)

会给予

   var_1 var_2 key  value
0      1   one   a     12
1      1   one   a     12

但这感觉可以大大改善,我不确定是否可以将其推广到其他行。

编辑

我可以使用诸如

之类的字典来作为数据框
all_keys = functools.reduce(lambda x,y: x+y , [list(x.keys()) for x in var3])
all_values = functools.reduce(lambda x,y: x+y, [list(x.values()) for x in var3])
pd.DataFrame(dict( keys = all_keys, values = all_values ))

给予

    keys  values
0      a      12
1      b      44
2   this       9
3   that      33
4  there      82
5      x      19
6      y      38
7      z      12
8      t      90

但这不能回答我所问的问题

2 个答案:

答案 0 :(得分:1)

使用您的import pandas as pd var3 = pd.DataFrame(pd.DataFrame(df['var_3'].values.tolist()).stack().reset_index(level=1)) var3.columns = ['keys','values'] print(var3) keys values 0 a 12.0 0 b 44.0 1 this 9.0 1 that 33.0 1 there 82.0 2 x 19.0 2 y 38.0 2 z 12.0 2 t 90.0 df = df.join(var3) print(df)

pd.json_normalize

enter image description here

var3 = pd.DataFrame(pd.json_normalize(df.var_3).stack()).reset_index(level=1) var3.columns = ['keys','values']

  • 这可能更好
import android.opengl.GLU
// widthScreen and heightScreen values will be different for port and land orientation
private var view: IntArray = intArrayOf(0, 0, widthScreen, heightScreen)
private var windowCoordinates = FloatArray(3)
...
// modelX, modelY, modelZ - model coordinates of vertex
GLU.gluProject(modelX, modelY, modelZ, modelViewMatrix, 0, 
     projectionMatrix, 0, view, 0, windowCoordinates, 0)

// coordinates (pixels) of the screen
val x = coordinatesWindow[0]
val y = coordinatesWindow[1]

答案 1 :(得分:0)

 private static Random random = new Random(); 
 public static string Random(int length)
     {   
          var stringChars = new char[length];

          for (int i = 0; i < length; i++)
              {
                  stringChars[i] = (char)random.Next(0x30, 0x7a);                  
                  return new string(stringChars);
              }
     }

输出

def custom_melt(df):
    vals = []
    for row in df.itertuples():
        for k, v in row.var_3.items():
            vals.append({'var_1': row.var_1,
                         'var_2': row.var_2,
                         'variable': 'key',
                         'value': k})
            vals.append({'var_1': row.var_1,
                         'var_2': row.var_2,
                         'variable': 'value',
                         'value': v})
    return pd.DataFrame(vals).sort_values(['var_1', 'var_2', 'variable'])