有效地标记大型数据框中的每一行

时间:2016-06-28 13:21:17

标签: pandas

我的文件包含2015年6月+ 365天的日期。我使用它作为查找表,因为有自定义的业务日期(仅观察到某些假期,并且由于内部原因,有一些无工作日期)。使用客户业务日期抵消的速度非常慢,有350万条记录。

initial_date | day_1      | day_2      | day_3      | ... | day_365
2015-06-01     2015-06-02   2015-06-03   2015-06-04
2015-06-02     2015-06-03   2015-06-04   2015-06-05

我们的想法是根据特定条目以来的(自定义)营业日期的数量来“标记”数据中的每一行。有更好的方法吗?

例如,如果在2016-06-28发生新条目,则会将其标记为'initial_date'day_1明天,day_2是第二天,day_3是星期五,day_4是下周一。

我这样做的天真的方法是创建一个基本上这样做的循环:

 df.day_1_label = np.where(df.date == df.day_1, 'Day 1', '')
 df.day_2_label = np.where(df.date == df.day_2, 'Day 2', '')

df.day_label = (df.day_1_label + df.day_2_label + ...).replace('', regex=True, inplace=True)

这将导致每行一个标签,然后我可以汇总或绘制。最终这将用于预测。 initial_date + the subset of customers from previous dates = total customers

此外,根据发生的事件,一部分客户将来会发生某种事件。我想知道平均来自initial_date的业务日期。因此,如果我们今天有100个客户,那么一定比例的客户将在明年7月15日或之前举办一场活动。

使用一些示例数据编辑 - pastebin:

http://pastebin.com/ZuE1Q2KJ

所以我要找的输出是day_label。这基本上检查日期==从day_0到day_n的每个日期。有没有更好的方法来填补它?我只是想尝试将每行的日期与其中一个day_列中的值进行匹配。

1 个答案:

答案 0 :(得分:1)

我认为如果您的数据看起来像我认为的那样,这可以更有效率。

假设您有日期日历(2015年6月+ 365天)和数据框,例如:

var html = "<div class=\"cf\">" +
            "    <span class=\"labelText ohneFeldhilfe\">Name</span>" +
            "    <p>Firstname Lastname</p>" +
            "</div>";
var doc = new HtmlDocument();
doc.LoadHtml(html);

var paragraphs = doc.DocumentNode.Descendants("div") // Get all divs..
    .Where(d => d.Attributes.Contains("class") && d.Attributes["class"].Value == "cf") // .. that have a class called cf ..
    .Select(d => d.Descendants("p").First()); // .. inside those divs select the first paragraph

foreach (var paragraph in paragraphs)
{
    var nameParts = paragraph.InnerText.Split(' ');

    Console.WriteLine("First name: " + nameParts[0]);
    Console.WriteLine("Last name: " + nameParts[1]);
}

在numpy.datetime类型中保留日期更有效,所以我转换:

cal = ['2015-06-01', '2015-06-02', '2015-06-03', '2015-06-04', '2015-06-08',
       '2015-06-09']

df = pd.DataFrame({'date': ['2015-06-04', '2015-06-09', '2015-06-09'],
                   'initial_date': ['2015-06-02', '2015-06-02', '2015-06-01']})

现在,让我们将df['date'] = df['date'].astype(np.datetime64) df['initial_date'] = df['initial_date'].astype(np.datetime64) 转换为快速查找表:

cal

修改

以上# converting types: cal = np.asarray(cal, dtype=np.datetime64) # lookup series s_cal = pd.Series(range(len(cal)), index=cal) # a convenience lookup function def lookup(dates): return s_cal[dates].reset_index(drop=True) 会返回一个lookup的系列,该系列可能与RangeIndex的索引不同(这会在将结果分配给列时导致问题)。因此,重写此查找可能会更好,以便它返回一个简单的numpy数组:

df

可以在def lookup2(dates): return s_cal[dates].values 中设置正确的索引(取自输入lookup)。但是这样的解决方案不够灵活(需要输入为dates)或不必要的复杂。

系列:

Series

以及它如何运作:

s_cal
Out[220]: 
2015-06-01    0
2015-06-02    1
2015-06-03    2
2015-06-04    3
2015-06-08    4
2015-06-09    5
dtype: int64

其余的很简单。这会在数据框中添加一列整数(日差):

lookup(df.date)
Out[221]: 
0    3
1    5
2    5
dtype: int64

lookup2(df.date)
Out[36]: array([3, 5, 5])

如果您想将其转换为标签:

df['day_label'] = lookup2(df.date) - lookup2(df.initial_date)

希望这是你想要的。