pandas 代码请教

2018-01-11 23:09:13 +08:00
 w12103
for i, row in dset.iterrows():
    hteam = row['home']
    vteam = row['visitor']
    row['hlastwin'] = won_last[hteam]
    row['vlastwin'] = won_last[vteam]
    dset.iloc[i] = row

如上,dset 是一个 DataFrame,遍历每行并为每行增加两个元素,期望遍历结束后 dset 应该增加两列,但实际 dset 没有变化,最后一行代码为啥没效果,有大神能说一下原因吗(搜了一通没啥结果。。),多谢~

2979 次点击
所在节点    Python
8 条回复
shidenggui
2018-01-11 23:40:00 +08:00
应该这样写是可以的 dset.assign(hlastwin=lambda x: won_last[x.home], vlastwin=lambda x: won_last[x.visitor])
imn1
2018-01-11 23:50:29 +08:00
iloc/loc 等一般只能用于读取,应该只是类似一个 copy 的性质
改变 df 要另外赋值

另外,这样轮循有点笨啊,应该整列复制,或者 join/merge
zeq
2018-01-12 00:38:51 +08:00
```
dest['hlastwin'] = dest['home'].map(lambda h: won_last[h])
```

大概是这么一个思路
neoblackcap
2018-01-12 09:23:06 +08:00
上面几楼都说了,我加一句,pandas 是调用 numpy 的接口的,因此不要自己写循环。自己的循环是没有 Pandas 里面的对 dataframe 的操作快的。
fcfangcc
2018-01-12 09:51:50 +08:00
dset.loc[:, 'hlastwin'] = [won_last[i] for i in dset['home'].values]
dset.loc[:, 'vlastwin'] = [won_last[i] for i in dset['visitor'].values]
zyhuang
2018-01-12 09:54:56 +08:00
```
import pandas as pd
import numpy as np

won_last = pd.DataFrame({'lastwin':["lastwin_{}".format(i) for i in range(10000)]})
dset = pd.DataFrame(np.random.randint(10000, size=(10000, 2)),
columns=['home', 'visitor'])
In [2]:
%timeit dset.merge(won_last, left_on='home', right_index=True,how='left').merge(won_last, left_on='visitor', right_index=True,how='left', suffixes="hv")

7.16 ms ± 340 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


In [3]:
%timeit dset.assign(hlastwin=lambda x: [won_last.lastwin[ii] for ii in x.home], vlastwin=lambda x: [won_last.lastwin[ii] for ii in x.visitor])
355 ms ± 34.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

```
w12103
2018-01-12 10:29:30 +08:00
@imn1 按行遍历是因为 won_last 字典不断变动,我把代码补全一下。。
focusheart
2018-01-12 22:53:59 +08:00
你问的 iloc 那句不起作用,可以按楼上说的改,比如:

dset[i, 'hlastwin'] = won_last[hteam]

另外,看你的程序意思是每次循环里要给当前 row 填一个“主队上次赢”,“客队上次赢”这样的字段?
由于每个 row 都依赖上一次某条的记录,所以 merge 不太容易吧。
如果是这个情况的话,用 pandas 原地修改 dset 会比较慢,可以新开一个 list 来存;或者原始数据不放 pandas,直接用 list。
这样用 for 循环遍历的表现可能会好一些。

最后,这样一边迭代 dset,同时一边又修改 dset,感觉不太好。建议迭代 dset 的时候不要原地修改,而是将新 row 的数据放在其他变量里。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/422197

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX