如何将列表转换为Pandas数据框架

14

我有以下的代码:

rows =[]
for dt in new_info:
    x =  dt['state']
    est = dt['estimates']

    col_R = [val['choice'] for val in est if val['party'] == 'Rep']
    col_D = [val['choice'] for val in est if val['party'] == 'Dem']

    incumb = [val['party'] for val in est if val['incumbent'] == True ]

    rows.append((x, col_R, col_D, incumb))
现在我想将我的行列表转换为Pandas数据框。我的行列表的结构如下所示,列表有32个条目。
当我将其转换为Pandas数据框时,数据帧中的条目以列表的形式显示。
pd.DataFrame(rows, columns=["State", "R", "D", "incumbent"])  

enter image description here

但我希望我的数据框看起来像这样

enter image description here

新的信息变量长这样 enter image description here

2个回答

9

由于您关心列中的对象是列表,因此我建议使用生成器来去除包装项的列表:

import pandas as pd
import numpy as np
rows = [(u'KY', [u'McConnell'], [u'Grimes'], [u'Rep']),
        (u'AR', [u'Cotton'], [u'Pryor'], [u'Dem']),
        (u'MI', [u'Land'], [u'Peters'], [])]

def get(r, nth):
    '''helper function to retrieve item from nth list in row r'''
    return r[nth][0] if r[nth] else np.nan

def remove_list_items(list_of_records):
    for r in list_of_records:
        yield r[0], get(r, 1), get(r, 2), get(r, 3)

生成器的工作原理类似于此函数,但不同的是它不会在内存中无谓地实例化列表作为中间步骤,而是将列表中每一行要传递给消费者:
def remove_list_items(list_of_records):
    result = []
    for r in list_of_records:
        result.append((r[0], get(r, 1), get(r, 2), get(r, 3)))
    return result

然后通过生成器将您的数据组成 DataFrame(或者如果希望,使用列表版本)。

>>> df = pd.DataFrame.from_records(
        remove_list_items(rows), 
        columns=["State", "R", "D", "incumbent"])
>>> df
  State          R       D incumbent
0    KY  McConnell  Grimes       Rep
1    AR     Cotton   Pryor       Dem
2    MI       Land  Peters       NaN

你也可以使用列表推导式或生成器表达式(如下所示)来实现基本相同的功能:

>>> df = pd.DataFrame.from_records(
      ((r[0], get(r, 1), get(r, 2), get(r, 3)) for r in rows), 
      columns=["State", "R", "D", "incumbent"])

让我们在聊天中继续这个讨论 - Russia Must Remove Putin

7
你可以使用Python内置的列表操作,像这样做:

您可以使用一些内置的Python列表操作,例如:

df['col1'] = df['col1'].apply(lambda i: ''.join(i))

这将产生:

    col1 col2
0    a  [d]
1    b  [e]
2    c  [f]

很明显,col2没有进行格式化以展示对比。

编辑

如OP所要求,如果您想对所有列实施apply(lambda...),则可以通过显式设置每个列,使用类似上面的行来替换'col1'以修改您希望更改的每个列名,或者您可以像这样遍历每一列:

如果您有一个数据框类型的数据,则可以:

x = [['a'],['b'],['c'],['d']]
y = [['e'],['f'],['g'],['h']]
z = [['i'],['j'],['k'],['l']]

df = pd.DataFrame({'col1':x, 'col2':y, 'col3':z})

然后您可以循环遍历列。
for col in df.columns:
    df[col] = df[col].apply(lambda i: ''.join(i))

将一个以以下方式开始的数据框进行转换:

   col1 col2 col3
0  [a]  [e]  [i]
1  [b]  [f]  [j]
2  [c]  [g]  [k]
3  [d]  [h]  [l]

并变成

    col1 col2 col3
0    a    e    i
1    b    f    j
2    c    g    k
3    d    h    l

@ElizabethSusanJoseph,我的解决方案不能解决你的问题吗? - alacy
但是我如何将其应用于整个数据框?能否编辑您的答案以回答我的问题,这将非常有帮助。 - Elizabeth Susan Joseph
new_df = pd.DataFrame(rows, columns=["State", "R", "D", "incumbent"]) 如果我执行你的代码 new_df[['R', 'D', 'incumbent']].apply(lambda i: ''.join(i)),会出现错误。 - Elizabeth Susan Joseph
你的解决方案更简单,但是我遇到了一个“所有数组必须具有相同长度”的值错误。这是完整的代码版本:https://bpaste.net/show/76cb1f8d3036 - Elizabeth Susan Joseph
非常感谢,我一定会实现这个。 - Elizabeth Susan Joseph
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接