带列表的Pandas Columns操作

时间:2017-07-05 11:45:28

标签: python pandas

我有一个包含两列的pandas数据框,第一个只有一个日期('action_date'),第二个有一个日期列表('verification_date')。我正在尝试计算'action_date'中的日期与相应'verification_date'列中列表中的每个日期之间的时差,然后使用在verification_date中具有相同差异的日期数填充df新列超过或低于360天。

这是我的代码:

df = pd.DataFrame()
df['action_date'] = ['2017-01-01', '2017-01-01', '2017-01-03']
df['action_date'] = pd.to_datetime(df['action_date'], format="%Y-%m-%d")
df['verification_date'] = ['2016-01-01', '2015-01-08', '2017-01-01']
df['verification_date'] = pd.to_datetime(df['verification_date'], format="%Y-%m-%d")
df['user_name'] = ['abc', 'wdt', 'sdf']
df.index = df.action_date
df = df.groupby(pd.TimeGrouper(freq='2D'))['verification_date'].apply(list).reset_index()


def make_columns(df):
    df = df
    for i in range(len(df)):  
        over_360 = []
        under_360 = []
        for w in [(df['action_date'][i]-x).days for x in df['verification_date'][i]]:
            if w > 360:
                over_360.append(w)
            else:
                under_360.append(w)
        df['over_360'] = len(over_360)
        df['under_360'] = len(under_360)
return df

make_columns(df)

这种方式有效除了df每行有相同的值,因为日期不同,所以不是这样。例如,在数据框的第一行中,action_date与verification_date列中列表中的两个项之间存在超过360天的差异,因此over_360列应填充为2.但是,它是空的相反,under_360列填充为1,这仅对'action_date'中的第二行准确。

我有一种感觉,我只是弄乱了循环,但我真的被卡住了。谢谢大家的帮助!

2 个答案:

答案 0 :(得分:1)

您的问题是您始终使用以下行的最后一次计算值更新整个列:

df['over_360'] = len(over_360)
df['under_360'] = len(under_360)

您想要做的是相应地设置每个行计算的值,您可以通过将以上行替换为以下行来执行此操作:

df.set_value(i,'over_360',len(over_360))
df.set_value(i,'under_360',len(under_360))

它的作用是,它在行i和列over_360under_360中设置一个值。

您可以了解有关它的更多信息here

如果您不喜欢使用set_values,也可以使用:

df.ix[i,'over_360'] = len(over_360)
df.ix[i,'under_360'] = len(under_360)

您可以查看dataframe.ix here

答案 1 :(得分:1)

你可能想试试这个:

df['over_360'] = df.apply(lambda x: sum([((x['action_date'] - i).days >360) for i in x['verification_date']]) , axis=1)
df['under_360'] = df.apply(lambda x: sum([((x['action_date'] - i).days <360) for i in x['verification_date']]) , axis=1)

我相信它应该快一点。 如果== 360,您没有指定要执行的操作,因此您只需更改&gt;或者&lt;进入&gt; =或&lt; =。