使用pandas

时间:2018-02-14 22:20:30

标签: python pandas

我有一个像这样的json文件:

{
  "A": {
    "type1": [
      2,
      26,
      288,
      ...
     ],
     "type2": [
      2,
      3,
      5,
      ...
     ],
     "type3": [
      23,
      26,
      288,
      ...
     ]
  },
  "B": {
    "type1": [
      2,
      26,
      288,
      ...
     ],
     "type2": [
      2,
      3,
      5,
      ...
     ],
     "type3": [
      23,
      26,
      288,
      ...
     ]
  },
...
  "K": {
    "type1": [
      2,
      26,
      288,
      ...
     ],
     "type2": [
      2,
      3,
      5,
      ...
     ],
     "type3": [
      23,
      26,
      288,
      ...
     ]
  }
}

以下是复制的示例字典(我从A到J有大约20列,但只有3种类型:type1,type2,type3):

pd.DataFrame({'A': {'type1': ['32',
   '21',
   '43',
   '43',
   '43',
   '43',
   '43',
   '43'],
  'type2': [
   0.133333333333333,
   0.36666666666666703,
   0.1,
   0.30000000000000004,
   0.16666666666666702,
   0.033333333333333,
   0.2,
   0.066666666666666],
  'type3': [
   3,
   9,
   5,
   1,
   6,
   2]},
 'B': {'type1': [
   '43',
   '43',
   '43',
   '43',
   '43'],
  'type2': [
   0.23333333333333303,
   0.266666666666667,
   0.30000000000000004,
   0.5666666666666671,
   0.16666666666666702,
   0.266666666666667],
  'type3': [
   10,
   6,
   17,
   7,
   8,
   9,
   17,
   5,
   8]},
 'C': {'type1': [
   '43',
   '43',
   '43',
   '43',
   '43',
   '43'],
  'type2': [
   5.23333333333333,
   6.1,
   5.4,
   3.23333333333333,
   17.4,
   5.56666666666667,
   10.4333333333333,
   2.1],
  'type3': [
   183,
   162,
   97,
   522,
   167,
   313,
   63]},
 })

给出这样的df: enter image description here

我的df最终应该是这样的:

  type1  type2  type3
A 32     0.13    3
A 21     0.36    9
A
........
B
........
C
........
J

所以我换了它: enter image description here 但后来我不确定如何解压缩这些列表。我每次尝试时都会遇到一些循环:

for x in df.index:
    for y in df.loc[x]["type1"]:
        df.iloc[index] = df.append({"index": x, "type": y}, ignore_index=True)
        index += 1

显然不是那种方式。

我想知道是否有更简单的方法,也许是因为我加载了json?

谢谢!

3 个答案:

答案 0 :(得分:4)

我在这里使用for循环.apply(pd.Series).stack是关键

df=df.T
l=[df[x].apply(pd.Series).stack() for x in df.columns]

s=pd.concat(l,1).reset_index(level=1,drop=True)
s.columns=df.columns

s
Out[347]: 
  type1      type2  type3
A    32   0.133333    3.0
A    21   0.366667    9.0
A    43   0.100000    5.0
A    43   0.300000    1.0
A    43   0.166667    6.0
A    43   0.033333    2.0
A    43   0.200000    NaN
A    43   0.066667    NaN
B    43   0.233333   10.0
B    43   0.266667    6.0
B    43   0.300000   17.0
B    43   0.566667    7.0
B    43   0.166667    8.0
B   NaN   0.266667    9.0
B   NaN        NaN   17.0
B   NaN        NaN    5.0
B   NaN        NaN    8.0
C    43   5.233333  183.0
C    43   6.100000  162.0
C    43   5.400000   97.0
C    43   3.233333  522.0
C    43  17.400000  167.0
C    43   5.566667  313.0
C   NaN  10.433333   63.0
C   NaN   2.100000    NaN

答案 1 :(得分:3)

没有明确的解决方案,因为列表长度不一样。所以首先你要照顾它,也许用零填充:

# assuming 'data' is your dict
for x in data:    
    max_length = max([len(data[x][y]) for y in data[x]])    
    for y in data[x]:
        data[x][y] += [np.nan] * (max_length - len(data[x][y]))

然后你可以用面板导入并玩弄索引和排序,直到你得到你想要的东西:)

df = pd.Panel.from_dict(data).to_frame(filter_observations=False).stack().unstack(1).swaplevel(0, 1).sort_index()

minor   type1      type2 type3
  major                       
A 0        32   0.133333     3
  1        21   0.366667     9
  2        43        0.1     5
  3        43        0.3     1
  4        43   0.166667     6
  5        43  0.0333333     2
  6        43        0.2   NaN
  7        43  0.0666667   NaN
B 0        43   0.233333    10
  1        43   0.266667     6
  2        43        0.3    17
  3        43   0.566667     7
  4        43   0.166667     8
  5       NaN   0.266667     9
  6       NaN        NaN    17
  7       NaN        NaN     5
  8       NaN        NaN     8
C 0        43    5.23333   183
  1        43        6.1   162
  2        43        5.4    97
  3        43    3.23333   522
  4        43       17.4   167
  5        43    5.56667   313
  6       NaN    10.4333    63
  7       NaN        2.1   NaN

答案 2 :(得分:2)

Wen和ascripter的令人敬畏的创意答案。 ascripter的答案是最快的,但值得注意的是Panel is deprecated并将在未来版本中删除。请参阅上面的链接以了解替代方案。

以Wen的代码为基础,可以使用values.tolist()而不是apply()来加速:

In[1]
df = pd.DataFrame.from_dict(data).transpose()

def my_test(df):
    l = [pd.DataFrame(df[col].values.tolist(), index=df.index).stack() for col in df.columns]
    df2 = pd.concat(l, axis=1).reset_index(level=1, drop=True)
    df2.columns = df.columns
    return df2

def wen_test(df):
    l=[df[x].apply(pd.Series).stack() for x in df.columns]
    s=pd.concat(l,1).reset_index(level=1,drop=True)
    s.columns=df.columns
    return s

%timeit my_test(df)
%timeit wen_test(df) 

Out[1]
100 loops, best of 3: 13.2 ms per loop
100 loops, best of 3: 15.7 ms per loop