为了账号安全,请及时绑定邮箱和手机立即绑定

将Pandas列中的字典/列表拆分为单独的列

将Pandas列中的字典/列表拆分为单独的列

Cats萌萌 2019-07-12 10:03:52
将Pandas列中的字典/列表拆分为单独的列我将数据保存在PostgreSQL数据库中。我正在使用Python2.7查询这些数据,并将其转换为PandasDataFrame。但是,这个dataframe的最后一列有一个字典(或List?)其中的价值。DataFrame如下所示:[1] dfStation ID     Pollutants8809           {"a": "46", "b": "3", "c": "12"}8810           {"a": "36", "b": "5", "c": "8"}8811           {"b": "2", "c": "7"}8812           {"c": "11"}8813           {"a": "82", "c": "15"}我需要将该列拆分为不同的列,以便DataFrame看起来如下所示:[2] df2Station ID     a      b       c8809           46     3       128810           36     5       88811           NaN    2       78812           NaN    NaN     118813           82     NaN     15我面临的主要问题是列表的长度不一样。但是所有的列表只包含相同的3个值:a、b和c,并且它们总是以相同的顺序出现(a第一,b第二,第三次)。下面的代码用于正确地返回我想要的东西(Df 2)。[3] df [4] objs = [df, pandas.DataFrame(df['Pollutant Levels'].tolist()).iloc[:, :3]][5] df2 = pandas.concat(objs, axis=1).drop('Pollutant Levels', axis=1)[6] print(df2)上周我还在运行这段代码,它运行得很好。但是现在我的代码被破坏了,我从[4]行得到了这个错误:IndexError: out-of-bounds on slice (end) 我没有对代码做任何更改,但现在得到了错误。我觉得这是因为我的方法不健全或不恰当。任何建议或指导,如何将这一列的列表分成不同的列,将不胜感激!编辑:我认为.tolist()和.application方法不适用于我的代码,因为它是一个Unicode字符串,即:#My data format u{'a': '1', 'b': '2', 'c': '3'}#and not{u'a': '1', u'b': '2', u'c': '3'}数据正在以这种格式从PostgreSQL数据库中导入。在这个问题上有什么帮助或想法吗?有办法转换Unicode吗?
查看完整描述

3 回答

?
繁星淼淼

TA贡献1775条经验 获得超11个赞

若要将字符串转换为实际的dict,可以执行以下操作df['Pollutant Levels'].map(eval)..之后,可以使用下面的解决方案将DECT转换为不同的列。


使用一个小示例,您可以使用.apply(pd.Series):


In [2]: df = pd.DataFrame({'a':[1,2,3], 'b':[{'c':1}, {'d':3}, {'c':5, 'd':6}]})


In [3]: df

Out[3]:

   a                   b

0  1           {u'c': 1}

1  2           {u'd': 3}

2  3  {u'c': 5, u'd': 6}


In [4]: df['b'].apply(pd.Series)

Out[4]:

     c    d

0  1.0  NaN

1  NaN  3.0

2  5.0  6.0

要将其与其余的dataframe结合起来,您可以concat具有上述结果的其他列:


In [7]: pd.concat([df.drop(['b'], axis=1), df['b'].apply(pd.Series)], axis=1)

Out[7]:

   a    c    d

0  1  1.0  NaN

1  2  NaN  3.0

2  3  5.0  6.0

使用您的代码,如果我省略了iloc部分:


In [15]: pd.concat([df.drop('b', axis=1), pd.DataFrame(df['b'].tolist())], axis=1)

Out[15]:

   a    c    d

0  1  1.0  NaN

1  2  NaN  3.0

2  3  5.0  6.0


查看完整回答
反对 回复 2019-07-12
?
千万里不及你

TA贡献1784条经验 获得超9个赞

试试这个:从SQL返回的数据必须转换为dict。或者可能是"Pollutant Levels"现在Pollutants'


   StationID                   Pollutants

0       8809  {"a":"46","b":"3","c":"12"}

1       8810   {"a":"36","b":"5","c":"8"}

2       8811            {"b":"2","c":"7"}

3       8812                   {"c":"11"}

4       8813          {"a":"82","c":"15"}



df2["Pollutants"] = df2["Pollutants"].apply(lambda x : dict(eval(x)) )

df3 = df2["Pollutants"].apply(pd.Series )


    a    b   c

0   46    3  12

1   36    5   8

2  NaN    2   7

3  NaN  NaN  11

4   82  NaN  15



result = pd.concat([df, df3], axis=1).drop('Pollutants', axis=1)

result


   StationID    a    b   c

0       8809   46    3  12

1       8810   36    5   8

2       8811  NaN    2   7

3       8812  NaN  NaN  11

4       8813   82  NaN  15


查看完整回答
反对 回复 2019-07-12
?
红糖糍粑

TA贡献1815条经验 获得超6个赞

我们不需要一个lambda函数。以下两种方法中的任何一种都可以安全地忽略字典的计算,如下所示:


方式1:两个步骤


# step 1: convert the `Pollutants` column to Pandas dataframe series

df_pol_ps = data_df['Pollutants'].apply(pd.Series)


df_pol_ps:

    a   b   c

0   46  3   12

1   36  5   8

2   NaN 2   7

3   NaN NaN 11

4   82  NaN 15


# step 2: concat columns `a, b, c` and drop/remove the `Pollutants` 

df_final = pd.concat([df, df_pol_ps], axis = 1).drop('Pollutants', axis = 1)


df_final:

    StationID   a   b   c

0   8809    46  3   12

1   8810    36  5   8

2   8811    NaN 2   7

3   8812    NaN NaN 11

4   8813    82  NaN 15

方法2:以上两个步骤可以一次完成:


df_final = pd.concat([df, df['Pollutants'].apply(pd.Series)], axis = 1).drop('Pollutants', axis = 1)


df_final:

    StationID   a   b   c

0   8809    46  3   12

1   8810    36  5   8

2   8811    NaN 2   7

3   8812    NaN NaN 11

4   8813    82  NaN 15


查看完整回答
反对 回复 2019-07-12
  • 3 回答
  • 0 关注
  • 3547 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信