首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从函数向Pandas Dataframe添加多列

从函数向Pandas Dataframe添加多列
EN

Stack Overflow用户
提问于 2015-05-04 17:32:40
回答 4查看 52K关注 0票数 39

我有一个有两列的pandas数据框mydf,这两列都是datetime数据类型:mydatemytime。我想再添加三个列:hourweekdayweeknum

代码语言:javascript
复制
def getH(t): #gives the hour
    return t.hour
def getW(d): #gives the week number
    return d.isocalendar()[1] 
def getD(d): #gives the weekday
    return d.weekday() # 0 for Monday, 6 for Sunday

mydf["hour"] = mydf.apply(lambda row:getH(row["mytime"]), axis=1)
mydf["weekday"] = mydf.apply(lambda row:getD(row["mydate"]), axis=1)
mydf["weeknum"] = mydf.apply(lambda row:getW(row["mydate"]), axis=1)

代码片段可以工作,但它的计算效率不高,因为它在数据帧中循环至少三次。我只想知道是否有更快和/或更优化的方法来做到这一点。例如,使用zip还是merge?例如,如果我只创建了一个返回三个元素的函数,我应该如何实现呢?为了说明这一点,函数如下:

代码语言:javascript
复制
def getHWd(d,t):
    return t.hour, d.isocalendar()[1], d.weekday()
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-05-04 17:57:10

下面是使用一个apply完成此任务的方法

比如说,df就像

代码语言:javascript
复制
In [64]: df
Out[64]:
       mydate     mytime
0  2011-01-01 2011-11-14
1  2011-01-02 2011-11-15
2  2011-01-03 2011-11-16
3  2011-01-04 2011-11-17
4  2011-01-05 2011-11-18
5  2011-01-06 2011-11-19
6  2011-01-07 2011-11-20
7  2011-01-08 2011-11-21
8  2011-01-09 2011-11-22
9  2011-01-10 2011-11-23
10 2011-01-11 2011-11-24
11 2011-01-12 2011-11-25

为了提高可读性,我们将把lambda函数去掉,并将其定义为

代码语言:javascript
复制
In [65]: lambdafunc = lambda x: pd.Series([x['mytime'].hour,
                                           x['mydate'].isocalendar()[1],
                                           x['mydate'].weekday()])

和,apply并将结果存储到df[['hour', 'weekday', 'weeknum']]

代码语言:javascript
复制
In [66]: df[['hour', 'weekday', 'weeknum']] = df.apply(lambdafunc, axis=1)

并且,输出结果如下

代码语言:javascript
复制
In [67]: df
Out[67]:
       mydate     mytime  hour  weekday  weeknum
0  2011-01-01 2011-11-14     0       52        5
1  2011-01-02 2011-11-15     0       52        6
2  2011-01-03 2011-11-16     0        1        0
3  2011-01-04 2011-11-17     0        1        1
4  2011-01-05 2011-11-18     0        1        2
5  2011-01-06 2011-11-19     0        1        3
6  2011-01-07 2011-11-20     0        1        4
7  2011-01-08 2011-11-21     0        1        5
8  2011-01-09 2011-11-22     0        1        6
9  2011-01-10 2011-11-23     0        2        0
10 2011-01-11 2011-11-24     0        2        1
11 2011-01-12 2011-11-25     0        2        2
票数 55
EN

Stack Overflow用户

发布于 2015-09-25 08:53:03

要补充John Galt's answer

根据lambdafunc执行的任务,您可能会体验到一些加速,方法是将apply的结果存储在新的DataFrame中,然后加入原始结果:

代码语言:javascript
复制
lambdafunc = lambda x: pd.Series([x['mytime'].hour,
                                  x['mydate'].isocalendar()[1],
                                  x['mydate'].weekday()])

newcols = df.apply(lambdafunc, axis=1)
newcols.columns = ['hour', 'weekday', 'weeknum']
newdf = df.join(newcols) 

即使您看不到速度的提高,我也建议您使用join。您将能够避免直接在列上赋值时可能弹出的(总是令人讨厌的) SettingWithCopyWarning

代码语言:javascript
复制
SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
票数 18
EN

Stack Overflow用户

发布于 2019-02-26 09:45:10

您可以在更简洁的方法中完成此操作,方法是让所应用的函数返回一个带有命名元素的pd.Series

代码语言:javascript
复制
def process(row):
    return pd.Series(dict(b=row["a"] * 2, c=row["a"] + 2))


my_df = pd.DataFrame(dict(a=range(10)))
new_df = my_df.join(my_df.apply(process, axis="columns"))

结果是:

代码语言:javascript
复制
   a   b   c
0  0   0   2
1  1   2   3
2  2   4   4
3  3   6   5
4  4   8   6
5  5  10   7
6  6  12   8
7  7  14   9
8  8  16  10
9  9  18  11
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30026815

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档