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

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

我将数据保存在PostgreSQL数据库中。我正在使用Python2.7查询这些数据,并将其转换为PandasDataFrame。但是,这个dataframe的最后一列有一个字典(或List?)其中的价值。DataFrame如下所示:


[1] df

Station ID     Pollutants

8809           {"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] df2

Station ID     a      b       c

8809           46     3       12

8810           36     5       8

8811           NaN    2       7

8812           NaN    NaN     11

8813           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吗?


Cats萌萌
浏览 3549回答 3
3回答

繁星淼淼

若要将字符串转换为实际的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]: dfOut[3]:   a                   b0  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    d0  1.0  NaN1  NaN  3.02  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    d0  1  1.0  NaN1  2  NaN  3.02  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    d0  1  1.0  NaN1  2  NaN  3.02  3  5.0  6.0

千万里不及你

试试这个:从SQL返回的数据必须转换为dict。或者可能是"Pollutant Levels"现在Pollutants'   StationID                   Pollutants0       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   c0   46    3  121   36    5   82  NaN    2   73  NaN  NaN  114   82  NaN  15result = pd.concat([df, df3], axis=1).drop('Pollutants', axis=1)result   StationID    a    b   c0       8809   46    3  121       8810   36    5   82       8811  NaN    2   73       8812  NaN  NaN  114       8813   82  NaN  15

红糖糍粑

我们不需要一个lambda函数。以下两种方法中的任何一种都可以安全地忽略字典的计算,如下所示:方式1:两个步骤# step 1: convert the `Pollutants` column to Pandas dataframe seriesdf_pol_ps = data_df['Pollutants'].apply(pd.Series)df_pol_ps:    a   b   c0   46  3   121   36  5   82   NaN 2   73   NaN NaN 114   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   c0   8809    46  3   121   8810    36  5   82   8811    NaN 2   73   8812    NaN NaN 114   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   c0   8809    46  3   121   8810    36  5   82   8811    NaN 2   73   8812    NaN NaN 114   8813    82  NaN 15
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python