如何使用for循环构建和填充pandas数据框?

105

这是我运行的一段简单代码示例,我希望将结果放入pandas数据框中(除非有更好的选项):

for p in game.players.passing():
    print p, p.team, p.passing_att, p.passer_rating()

R.Wilson SEA 29 55.7
J.Ryan SEA 1 158.3
A.Rodgers GB 34 55.8

使用以下代码:

d = []
for p in game.players.passing():
    d = [{'Player': p, 'Team': p.team, 'Passer Rating':
        p.passer_rating()}]

pd.DataFrame(d)

我可以得到:

    Passer Rating   Player      Team
  0 55.8            A.Rodgers   GB

这是一个1x3的数据框,我明白为什么只有一行,但我不知道如何按正确的顺序添加多行。理想情况下,解决方案可以处理n个行(基于p),如果列数可以根据请求的统计量数量进行设置,那将是很棒的(尽管不是必要的)。有什么建议吗?谢谢!


你正在每次迭代时覆盖你的列表,而不是添加。 - Paul H
我明白它的问题所在,但是我无法弄清楚如何使其正常工作。这只是我能够接近的最佳方案。 - c.j.mcdonn
1
下面的答案可行。你也可以在循环中使用 d.append({'Player': ...})。Python 列表文档非常不错。 - Paul H
1
你还应该澄清你的问题,说明真正的问题:你无法将数据附加到空列表中。 (你似乎非常了解如何从字典列表创建数据帧) - Paul H
1
虽然我认为我理解了你的意思,但我相信我所提出的问题实际上是我“更喜欢”的,而我发布的代码是在请求帮助之前最接近的。 - c.j.mcdonn
大多数Pandas的数字操作都可以向量化 - 这意味着它们比常规迭代要快得多。但是,有些操作(例如字符串和正则表达式)本质上很难向量化。在这种情况下,重要的是要理解如何遍历您的数据。有关何时以及如何遍历数据的更多信息,请阅读使用Pandas的for循环-我应该关心什么? - cs95
4个回答

144

最简单的答案是 Paul H 提出的:

d = []
for p in game.players.passing():
    d.append(
        {
            'Player': p,
            'Team': p.team,
            'Passer Rating':  p.passer_rating()
        }
    )

pd.DataFrame(d)

但是如果你真的想要“从循环中构建和填充数据框”(顺便说一句,我不建议这样做),那么以下是如何实现的。

d = pd.DataFrame()

for p in game.players.passing():
    temp = pd.DataFrame(
        {
            'Player': p,
            'Team': p.team,
            'Passer Rating': p.passer_rating()
        }
    )

    d = pd.concat([d, temp])

2
将字典附加到列表中并仅在结束时创建' df '是否更具优越性能,还是更易读呢? - ryantuck
3
性能。引用文档中的话:...concat(因此append)会创建数据的完整副本,并且......频繁重复使用此函数可能会导致性能受到显著影响。 - Nick Marinakis
@NickMarinakis:我不理解你的评论:“如果你真的想要“从循环中构建和填充数据框”(顺便说一句,我不推荐这样做)”。那么如果不通过循环,你还能用什么方式构建数据框呢? - stackoverflowuser2010
6
我的评论意思是你不应该创建一个数据帧,然后循环遍历数据来填充它。每次使用pd.concat时都会完全复制数据。这非常低效。相反,只需创建一个不同的数据结构(例如一个字典列表),然后一次性将其转换为数据帧。 - Nick Marinakis
1
@NickMarinakis:好的。在你的回答的第一部分中,你仍然使用循环(逐行构建一个list of dict),然后一次性将整个东西转换为DataFrame。在第二个(更糟糕的)解决方案中,你通过(concat)逐行附加DataFrame。明白了。 - stackoverflowuser2010

49

尝试使用列表推导式:

import pandas as pd

df = pd.DataFrame(
    [p, p.team, p.passing_att, p.passer_rating()] for p in game.players.passing()
)

2
这里的 df 是什么? - Cai
2
是指 df = pandas.DataFrame() 这样的形式吗?还是指 from pandas import DataFrame as df 这样的形式? - Cai
4
好的,那么在这种情况下,解决方案应该是 d = df([p, p.team, p.passing_att, p.passer_rating()] for p in game.players.passing()) 吗?(即调用 df 而不是索引?) - Cai
@Amit,你能否给你的解决方案添加更多的上下文信息?目前不清楚df实际上是什么。 - dkolmakov
在多次来到这里并没有找到帮助我的东西后,我找到了解决方案 ondf = df.append(pd.Series(mylist, index=df.columns), ignore_index=True) - vsm
显示剩余4条评论

37

制作一个元组列表,然后用它创建一个DataFrame:

d = []
for p in game.players.passing():
    d.append((p, p.team, p.passer_rating()))

pd.DataFrame(d, columns=('Player', 'Team', 'Passer Rating'))

元组列表的开销应该比字典列表小。我在下面进行了测试,但请记住,在大多数情况下,请将代码易于理解放在性能之前。

测试函数:

def with_tuples(loop_size=1e5):
    res = []

    for x in range(int(loop_size)):
        res.append((x-1, x, x+1))

    return pd.DataFrame(res, columns=("a", "b", "c"))

def with_dict(loop_size=1e5):
    res = []

    for x in range(int(loop_size)):
        res.append({"a":x-1, "b":x, "c":x+1})

    return pd.DataFrame(res)

结果:

%timeit -n 10 with_tuples()
# 10 loops, best of 3: 55.2 ms per loop

%timeit -n 10 with_dict()
# 10 loops, best of 3: 130 ms per loop

我在我的代码中尝试了这个,它与元组一起工作得非常好。只是想知道元组是不可变的。那么我们如何能够附加它们? - Sumit Pokhrel
1
@SumitPokhrel 元组是不可变的,但它们并没有被 append 改变。列表被附加到并因此被改变。 - Seanny123
你难道不认为追加某些东西就是将其从原始形式变异或改变吗?如果列表被添加而发生变异,那么为什么元组没有被添加而发生变异呢? - Sumit Pokhrel
1
@SumitPokhrel 因为你将元组附加到列表中:res=[(1,2)],然后 res.append((3,4)) 得到 [(1,2),(3,4)]。因此,元组没有被改变。 - Fee

1

我可能错了,但我认为@amit的被接受答案有一个bug。

from pandas import DataFrame as df
x = [1,2,3]
y = [7,8,9,10]

# this gives me a syntax error at 'for' (Python 3.7)
d1 = df[[a, "A", b, "B"] for a in x for b in y]

# this works
d2 = df([a, "A", b, "B"] for a in x for b in y)

# and if you want to add the column names on the fly
# note the additional parentheses
d3 = df(([a, "A", b, "B"] for a in x for b in y), columns = ("l","m","n","o"))

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