多索引切片(涉及时间序列/日期范围)不适用于DataFrame,但适用于Series

时间:2019-01-26 05:43:51

标签: python pandas

在日期范围内对多索引DataFrame进行切片似乎不起作用(未按切片方式返回数据帧),而对多索引Series执行相同的操作时,似乎没有效果。

例如:

# Create a multi-indexed DataFrame with time series as 'inner' index
idx = pd.MultiIndex.from_product([['id1', 'id2', 'id3'], pd.date_range('2019-01-01', '2019-01-05')], names=['id', 'date'])
cols = ['colA', 'colB']
example_df = pd.DataFrame(np.ones(30).reshape(15, 2), idx, cols)

example_df如下:

                colA    colB
id  date        
id1 2019-01-01  1.0     1.0
    2019-01-02  1.0     1.0
    2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0
id2 2019-01-01  1.0     1.0
    2019-01-02  1.0     1.0
    2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0
id3 2019-01-01  1.0     1.0
    2019-01-02  1.0     1.0
    2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0

尝试切片内部的“日期”索引级别,只需将DataFrame保持不变即可。

# Get all records for 3rd January 2019 onward, for all ids
idx = pd.IndexSlice
example_df.loc[idx[:, '2019-01-3':]] # yields example_df unchanged

所需的结果是:

                colA    colB
id  date        
id1 2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0
id2 2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0
id3 2019-01-03  1.0     1.0
    2019-01-04  1.0     1.0
    2019-01-05  1.0     1.0

奇怪的是,对系列进行切片会产生预期的结果

# Perform same slice but just for colA
example_df.colA.loc[idx[:, '2019-01-3':]]    

这会产生预期的结果

id   date      
id1  2019-01-03    1.0
     2019-01-04    1.0
     2019-01-05    1.0
id2  2019-01-03    1.0
     2019-01-04    1.0
     2019-01-05    1.0
id3  2019-01-03    1.0
     2019-01-04    1.0
     2019-01-05    1.0   

我在大熊猫0.23.1上。

赞赏有关如何获取适用于DataFrame版本的切片的任何输入。我知道我可以在内部日期索引上使用布尔掩码实现相同的结果,即

from datetime import datetime
inner_mask = example_df.index.get_level_values(1) >= datetime(2019, 1, 3)
example_df[inner_mask]

...但是我很想理解为什么这种切片方法不起作用(特别是当它适用于Series版本时)。谢谢。

1 个答案:

答案 0 :(得分:4)

您需要在DataFrame.loc中的第二个位置指定列print(example_df.loc[idx[:, '2019-01-3':], 'colA']) id date id1 2019-01-03 1.0 2019-01-04 1.0 2019-01-05 1.0 id2 2019-01-03 1.0 2019-01-04 1.0 2019-01-05 1.0 id3 2019-01-03 1.0 2019-01-04 1.0 2019-01-05 1.0 Name: colA, dtype: float64

DataFrame

如果要仅在列print(example_df.loc[idx[:, '2019-01-3':], ['colA']]) colA id date id1 2019-01-03 1.0 2019-01-04 1.0 2019-01-05 1.0 id2 2019-01-03 1.0 2019-01-04 1.0 2019-01-05 1.0 id3 2019-01-03 1.0 2019-01-04 1.0 2019-01-05 1.0 上使用一个元素列表:

print(example_df.loc[inner_mask, 'colA'])
id   date      
id1  2019-01-03    1.0
     2019-01-04    1.0
     2019-01-05    1.0
id2  2019-01-03    1.0
     2019-01-04    1.0
     2019-01-05    1.0
id3  2019-01-03    1.0
     2019-01-04    1.0
     2019-01-05    1.0
Name: colA, dtype: float64

print(example_df.loc[inner_mask, ['colA']])
                colA
id  date            
id1 2019-01-03   1.0
    2019-01-04   1.0
    2019-01-05   1.0
id2 2019-01-03   1.0
    2019-01-04   1.0
    2019-01-05   1.0
id3 2019-01-03   1.0
    2019-01-04   1.0
    2019-01-05   1.0

具有布尔型面罩的相同原理:

:

对于切片所有列,请使用print(example_df.loc[idx[:, '2019-01-3':], :]) colA colB id date id1 2019-01-03 1.0 1.0 2019-01-04 1.0 1.0 2019-01-05 1.0 1.0 id2 2019-01-03 1.0 1.0 2019-01-04 1.0 1.0 2019-01-05 1.0 1.0 id3 2019-01-03 1.0 1.0 2019-01-04 1.0 1.0 2019-01-05 1.0 1.0

login-submit.php page----


<?php

require 'includes\common.php';

$email = $_POST['e-mail'];
$email = mysqli_real_escape_string($con, $email);
$password = $_POST['password'];
$password = mysqli_real_escape_string($con, $password);
$password = MD5($password);
// Query checks if the email and password are present in the database.
$query = "SELECT id, email FROM admin WHERE email='" . $email . "' AND password='" . $password . "'";
$result = mysqli_query($con, $query)or die($mysqli_error($con));
$num = mysqli_num_rows($result);
// If the email and password are not present in the database, the mysqli_num_rows returns 0, it is assigned to $num.
if ($num == 0) {
  $error = "<span class='red'>Please enter correct E-mail id and Password</span>";
  header('location: login.php?error=' . $error);
} else {  
  $row = mysqli_fetch_array($result);
  $_SESSION['email'] = $row['email'];
  $_SESSION['user_id'] = $row['id'];
  header('location: index3.php');
}