Add Multiple Columns to Pandas Dataframe from Function

后端 未结 4 1079
执笔经年
执笔经年 2021-01-30 10:41

I have a pandas data frame mydf that has two columns,and both columns are datetime datatypes: mydate and mytime. I want to add three more

相关标签:
4条回答
  • 2021-01-30 11:16

    You can do this in a somewhat cleaner method by having the function you apply return a pd.Series with named elements:

    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"))
    

    The result is:

       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
    
    0 讨论(0)
  • 2021-01-30 11:19

    Here's on approach to do it using one apply

    Say, df is like

    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
    

    We'll take the lambda function out to separate line for readability and define it like

    In [65]: lambdafunc = lambda x: pd.Series([x['mytime'].hour,
                                               x['mydate'].isocalendar()[1],
                                               x['mydate'].weekday()])
    

    And, apply and store the result to df[['hour', 'weekday', 'weeknum']]

    In [66]: df[['hour', 'weekday', 'weeknum']] = df.apply(lambdafunc, axis=1)
    

    And, the output is like

    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
    
    0 讨论(0)
  • 2021-01-30 11:31

    To complement John Galt's answer:

    Depending on the task that is performed by lambdafunc, you may experience some speedup by storing the result of apply in a new DataFrame and then joining with the original:

    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) 
    

    Even if you do not see a speed improvement, I would recommend using the join. You will be able to avoid the (always annoying) SettingWithCopyWarning that may pop up when assigning directly on the columns:

    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
    
    0 讨论(0)
  • 2021-01-30 11:31
    def getWd(d):
        d.isocalendar()[1], d.weekday()
    def getH(t):
        return t.hour
    mydf["hour"] = zip(*df["mytime"].map(getH))
    mydf["weekday"], mydf["weeknum"] = zip(*df["mydate"].map(getWd))
    
    0 讨论(0)
提交回复
热议问题