Python——Chapter 7 Pandas Data Analysis Actual Combat

7.1 pandas commonly used data types

7.1.1 One-dimensional array and common operations

import pandas as pd
import matplotlib.pyplot as plt

#设置输出结果对齐方式
pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

#自动创建从0开始的非负整数索引
s1=pd.Series(range(1,20,5))
#使用字典创建Series,使用字典的“键”作为索引
s2=pd.Series({
    
    '语文':90,'数学':92,'Python':98,'物理':87,'化学':92})
#修改指定索引对应的值
s1[3]=-17
s2['语文']=94
print('s1原始数据'.ljust(20,'='))
print(s1)
s1原始数据==============
0     1
1     6
2    11
3   -17
dtype: int64
print('对s1所有数据求绝对值'.ljust(20,'='))
print(abs(s1))
对s1所有数据求绝对值=========
0     1
1     6
2    11
3    17
dtype: int64
print('s1所有的值加5'.ljust(20,'='))
print(s1+5)
s1所有的值加5============
0     6
1    11
2    16
3   -12
dtype: int64
print('s1的每行索引前面加上数字2'.ljust(20,'='))
print(s1.add_prefix(2))
s1的每行索引前面加上数字2======
20     1
21     6
22    11
23   -17
dtype: int64
print('s2原始数据'.ljust(20,'='))
print(s2)
s2原始数据==============
语文      94
数学      92
Python    98
物理      87
化学      92
dtype: int64
print('s2数据的直方图'.ljust(20,'='))
s2.hist()
plt.show()
s2数据的直方图============

insert image description here

print('s2的每行索引后面加上_张三'.ljust(20,'='))
print(s2.add_suffix('_张三'))
s2的每行索引后面加上_张三======
语文_张三      94
数学_张三      92
Python_张三    98
物理_张三      87
化学_张三      92
dtype: int64
print('s2最大值的索引'.ljust(20,'='))
print(s2.idxmax())
s2最大值的索引============
Python
print('测试s2的值是否在指定区间内'.ljust(20,'='))
print(s2.between(90,94,inclusive=True))
测试s2的值是否在指定区间内======
语文       True
数学       True
Python    False
物理      False
化学       True
dtype: bool
print('查看s2中大于中值的数据'.ljust(20,'='))
print(s2[s2>s2.median()])
查看s2中大于中值的数据========
语文      94
Python    98
dtype: int64
print('查看s2中90分以上的数据'.ljust(20,'='))
print(s2[s2>90])
查看s2中90分以上的数据=======
语文      94
数学      92
Python    98
化学      92
dtype: int64
print('s2与数字之间的运算'.ljust(20,'='))
print(round((s2**0.5)*10,1))
s2与数字之间的运算==========
语文      97.0
数学      95.9
Python    99.0
物理      93.3
化学      95.9
dtype: float64
print('s2的中值'.ljust(20,'='))
print(s2.median())
s2的中值===============
92.0
print('s2中最小的2个值'.ljust(20,'='))
print(s2.nsmallest(2))
s2中最小的2个值===========
物理    87
数学    92
dtype: int64
#两个等长Series对象之间可以进行四则运算和幂运算
#只对两个Series对象中都有的索引对应的值进行计算
#非共同索引对应的值为空值NaN
print('两个Series对象相加'.ljust(20,'='))
print(pd.Series(range(5))+pd.Series(range(5,10)))
两个Series对象相加========
0     5
1     7
2     9
3    11
4    13
dtype: int64
print('每个值的平方对5的余数'.ljust(20,'='))
print(pd.Series(range(5)).pipe(lambda x,y,z:(x**y)%z,2,5))
每个值的平方对5的余数=========
0    0
1    1
2    4
3    4
4    1
dtype: int64
print('每个值加3之后再乘以3'.ljust(20,'='))
print(pd.Series(range(5)).pipe(lambda x:x+3).pipe(lambda x:x*3))
每个值加3之后再乘以3=========
0     9
1    12
2    15
3    18
4    21
dtype: int64
print('每个值加3'.ljust(20,'='))
print(pd.Series(range(5)).apply(lambda x:x+3))
每个值加3===============
0    3
1    4
2    5
3    6
4    7
dtype: int64
print('标准差、无偏方差、无偏标准差'.ljust(20,'='))
print(pd.Series(range(5)).std())
print(pd.Series(range(5)).var())
print(pd.Series(range(5)).sem())
标准差、无偏方差、无偏标准差======
1.5811388300841898
2.5
0.7071067811865476
print('查看是否存在等价于True的值'.ljust(20,'='))
print(any(pd.Series([3,0,True])))
查看是否存在等价于True的值=====
True
print('查看是否所有值都等价于True'.ljust(20,'='))
print(all(pd.Series([3,0,True])))
查看是否所有值都等价于True=====
False

7.1.2 Time series and common operations

Time series objects are generally generated using the date_range() function of pandas. You can specify parameters such as the start and end range of the date and time, the time interval, and the number of data. The syntax is:

date_range(start=None, end=None, periods=None,freq=‘D’, tz=None, normalize=False,name=None, closed=None, **kwargs)

stard specifies the start date, end specifies the end date, and periods specifies the amount of data generated

freq specifies the time interval, D means days, W means weeks, H means hours

M means the last day of the month, MS means the first day of the month

T means minutes, Y means the last day of the year, YS means the first day of the year

print('间隔5天')
print(pd.date_range(start='20190601',end='20190630',freq='5D'))
间隔5天
DatetimeIndex(['2019-06-01', '2019-06-06', '2019-06-11', '2019-06-16',
               '2019-06-21', '2019-06-26'],
              dtype='datetime64[ns]', freq='5D')
print('间隔1周')
print(pd.date_range(start='20190601',end='20190630',freq='W'))
间隔1周
DatetimeIndex(['2019-06-02', '2019-06-09', '2019-06-16', '2019-06-23',
               '2019-06-30'],
              dtype='datetime64[ns]', freq='W-SUN')
print('间隔2天,5个数据')
print(pd.date_range(start='20190601',periods=5,freq='2D'))
间隔2天,5个数据
DatetimeIndex(['2019-06-01', '2019-06-03', '2019-06-05', '2019-06-07',
               '2019-06-09'],
              dtype='datetime64[ns]', freq='2D')
print('间隔3小时,8个数据'.ljust(30,'='))
print(pd.date_range(start='20190601',periods=8,freq='3H'))
间隔3小时,8个数据====================
DatetimeIndex(['2019-06-01 00:00:00', '2019-06-01 03:00:00',
               '2019-06-01 06:00:00', '2019-06-01 09:00:00',
               '2019-06-01 12:00:00', '2019-06-01 15:00:00',
               '2019-06-01 18:00:00', '2019-06-01 21:00:00'],
              dtype='datetime64[ns]', freq='3H')
print('3:00开始,间隔1分钟,12个数据')
print(pd.date_range(start='201906010300',periods=12,freq='T'))
3:00开始,间隔1分钟,12个数据
DatetimeIndex(['2019-06-01 03:00:00', '2019-06-01 03:01:00',
               '2019-06-01 03:02:00', '2019-06-01 03:03:00',
               '2019-06-01 03:04:00', '2019-06-01 03:05:00',
               '2019-06-01 03:06:00', '2019-06-01 03:07:00',
               '2019-06-01 03:08:00', '2019-06-01 03:09:00',
               '2019-06-01 03:10:00', '2019-06-01 03:11:00'],
              dtype='datetime64[ns]', freq='T')
print('间隔1月,月末最后一天')
print(pd.date_range(start='20190101',end='20191231',freq='M'))
间隔1月,月末最后一天
DatetimeIndex(['2019-01-31', '2019-02-28', '2019-03-31', '2019-04-30',
               '2019-05-31', '2019-06-30', '2019-07-31', '2019-08-31',
               '2019-09-30', '2019-10-31', '2019-11-30', '2019-12-31'],
              dtype='datetime64[ns]', freq='M')
print('间隔1年,6个数据,年末最后一天')
print(pd.date_range(start='20190101',periods=6,freq='A'))
间隔1年,6个数据,年末最后一天
DatetimeIndex(['2019-12-31', '2020-12-31', '2021-12-31', '2022-12-31',
               '2023-12-31', '2024-12-31'],
              dtype='datetime64[ns]', freq='A-DEC')
print('间隔1年,6个数据,年初第一天')
print(pd.date_range(start='20190101',periods=6,freq='AS'))
间隔1年,6个数据,年初第一天
DatetimeIndex(['2019-01-01', '2020-01-01', '2021-01-01', '2022-01-01',
               '2023-01-01', '2024-01-01'],
              dtype='datetime64[ns]', freq='AS-JAN')
#使用日期时间做索引,创建Series对象
data=pd.Series(index=pd.date_range(start='20190701',periods=24,freq='H'),data=range(24))
print('前5条数据')
print(data[:5])
前5条数据
2019-07-01 00:00:00    0
2019-07-01 01:00:00    1
2019-07-01 02:00:00    2
2019-07-01 03:00:00    3
2019-07-01 04:00:00    4
Freq: H, dtype: int64
print('3小时重采样,计算均值')
print(data.resample('3H').mean())
3小时重采样,计算均值
2019-07-01 00:00:00     1
2019-07-01 03:00:00     4
2019-07-01 06:00:00     7
2019-07-01 09:00:00    10
2019-07-01 12:00:00    13
2019-07-01 15:00:00    16
2019-07-01 18:00:00    19
2019-07-01 21:00:00    22
Freq: 3H, dtype: int64
print('5小时重采样,求和')
print(data.resample('5H').sum())
5小时重采样,求和
2019-07-01 00:00:00    10
2019-07-01 05:00:00    35
2019-07-01 10:00:00    60
2019-07-01 15:00:00    85
2019-07-01 20:00:00    86
Freq: 5H, dtype: int64
print('5小时重采样,统计OHLC值')
print(data.resample('5H').ohlc())
5小时重采样,统计OHLC值
                     open  high  low  close
2019-07-01 00:00:00     0     4    0      4
2019-07-01 05:00:00     5     9    5      9
2019-07-01 10:00:00    10    14   10     14
2019-07-01 15:00:00    15    19   15     19
2019-07-01 20:00:00    20    23   20     23
print('所有日期替换为第二天')
data.index=data.index+pd.Timedelta('1D')
print(data[:5])
所有日期替换为第二天
2019-07-02 00:00:00    0
2019-07-02 01:00:00    1
2019-07-02 02:00:00    2
2019-07-02 03:00:00    3
2019-07-02 04:00:00    4
Freq: H, dtype: int64
print('查看指定日期是周几')
print(pd.Timestamp('20190323').day_name())
查看指定日期是周几
Saturday
print('查看指定日期时间所在年是否为闰年')
print(pd.Timestamp('201909300800').is_leap_year)
查看指定日期时间所在年是否为闰年
False
print('查看指定日期所在的季度和月份')
day=pd.Timestamp('20191025')
print(day.quarter,day.month)
查看指定日期所在的季度和月份
4 10
print('转换为Python的日期时间对象')
print(day.to_pydatetime())
转换为Python的日期时间对象
2019-10-25 00:00:00

7.1.3 Two-dimensional array DataFrame

import numpy as np
import pandas as pd

pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df=pd.DataFrame(np.random.randint(1,20,(5,3)),index=range(5),columns=['A','B','C'])
print(df)
    A   B   C
0   9  16   6
1   2  17   1
2   9   5   7
3  16  16  14
4   9  12   1
df=pd.DataFrame(np.random.randint(5,15,(13,3)),
                index=pd.date_range(start='201907150900',
                                    end='201907152100',
                                    freq='H'),
                columns=['熟食','化妆品','日用品'])
print(df)
                     熟食  化妆品  日用品
2019-07-15 09:00:00    12      13      10
2019-07-15 10:00:00     6      10       5
2019-07-15 11:00:00     5      13      12
2019-07-15 12:00:00     5       5      12
2019-07-15 13:00:00    13      11      12
2019-07-15 14:00:00     7       6       9
2019-07-15 15:00:00    10      10      13
2019-07-15 16:00:00    14      10       7
2019-07-15 17:00:00    13      14      14
2019-07-15 18:00:00     6      13       9
2019-07-15 19:00:00     7       7      10
2019-07-15 20:00:00     8       9      13
2019-07-15 21:00:00    13      11       5
df=pd.DataFrame({
    
    '语文':[87,79,67,92],
                 '数学':[93,89,80,77],
                 '英语':[90,80,70,75]},
                index=['张三','李四','王五','赵六'])
print(df)
      语文  数学  英语
张三    87    93    90
李四    79    89    80
王五    67    80    70
赵六    92    77    75
df=pd.DataFrame({
    
    'A':range(5,10),'B':3})
print(df)
   A  B
0  5  3
1  6  3
2  7  3
3  8  3
4  9  3

7.2 DataFrame data processing and analysis in practice

7.2.1 Read the data in the Excel file

read_excel(io, sheetname=0, header=0, skiprows=None, skip_footer=0, index_col=None, names=None, parse_cols=None, parse_dates=False, date_parser=None, na_values=None, thousands=None, convert_float=True, has_index_names=None, converters=None, true_values=None, false_values=None, engine=None, squeeze=False, **kwds)

1) The parameter io is used to specify the Excel file to be read, which can be a file path, url or file object in the form of a string;

2) The parameter sheetname is used to specify the worksheet to be read. It can be an integer representing the serial number of the worksheet or a string representing the name of the worksheet. If you want to read multiple worksheets at the same time, you can use the form [0, 1, 'sheet3'] List, if you specify this parameter as None, it means to read all worksheets and return a dictionary containing multiple DataFrame structures, this parameter defaults to 0 (meaning to read the data in the first worksheet);

3) The parameter headers is used to specify the row index representing the header or column name in the worksheet, the default is 0, if there is no row as the header, you must explicitly specify headers=None;

4) The parameter skiprows is used to specify a list of row indexes to be skipped;

5) The parameter index_col is used to specify the column subscript used as the DataFrame index, which can be a list containing several column subscripts;

6) The parameter names are used to specify the column names used after reading the data;

7) The parameter thousands is used to specify the thousand separator when converting text to numbers. If there are numbers stored in text form in Excel, you can use this parameter;

8) The parameter usecols is used to specify the index or name of the column to be read. If the field type is determined, the form of {'col':type} can be used to improve the speed;

9) The parameter na_values ​​is used to specify which values ​​are interpreted as missing values.

import pandas as pd
pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df=pd.read_excel(r'超市营业额2.xlsx')
print(df[:10],end='\n\n')
   工号  姓名        日期           时段  交易额      柜台
0  1001  张三  2019-03-01   9:00-14:00  1664.0    化妆品
1  1002  李四  2019-03-01  14:00-21:00   954.0    化妆品
2  1003  王五  2019-03-01   9:00-14:00  1407.0      食品
3  1004  赵六  2019-03-01  14:00-21:00  1320.0      食品
4  1005  周七  2019-03-01   9:00-14:00   994.0    日用品
5  1006  钱八  2019-03-01  14:00-21:00  1421.0    日用品
6  1006  钱八  2019-03-01   9:00-14:00  1226.0  蔬菜水果
7  1001  张三  2019-03-01  14:00-21:00  1442.0  蔬菜水果
8  1001  张三  2019-03-02   9:00-14:00  1530.0    化妆品
9  1002  李四  2019-03-02  14:00-21:00  1395.0    化妆品

df1=pd.read_excel(r'超市营业额2.xlsx',skiprows=[1,3,5],index_col=1)
print(df1[:10])
      工号        日期           时段  交易额      柜台
姓名                                                   
李四  1002  2019-03-01  14:00-21:00   954.0    化妆品
赵六  1004  2019-03-01  14:00-21:00  1320.0      食品
钱八  1006  2019-03-01  14:00-21:00  1421.0    日用品
钱八  1006  2019-03-01   9:00-14:00  1226.0  蔬菜水果
张三  1001  2019-03-01  14:00-21:00  1442.0  蔬菜水果
张三  1001  2019-03-02   9:00-14:00  1530.0    化妆品
李四  1002  2019-03-02  14:00-21:00  1395.0    化妆品
王五  1003  2019-03-02   9:00-14:00   936.0      食品
赵六  1004  2019-03-02  14:00-21:00   906.0      食品
周七  1005  2019-03-02   9:00-14:00  1444.0    日用品

7.2.2 Filter data that meets specific conditions

There are four main categories of indexing or slicing of DataFrames:

Index single element: tag-based at, location-based iat

Slicing columns: use. to slice a single column, use [] to slice a single or multiple columns, label-based loc, position-based iloc

Slicing index: use [] to slice single or multiple lines, label-based loc, position-based iloc

Slice index and columns: label-based loc, position-based iloc

As a general rule, use at and loc based on labels, and use iat and iloc based on locations.

- based on the label at

at() queries the corresponding value according to the name of the row and column.

print(df.at[2,'交易额'])
1407.0

- based on location iat

iat() Query the corresponding value according to the position number of the row and column

print(df.iat[2,5])
食品
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 249 entries, 0 to 248
Data columns (total 6 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   工号      249 non-null    int64  
 1   姓名      249 non-null    object 
 2   日期      249 non-null    object 
 3   时段      249 non-null    object 
 4   交易额     246 non-null    float64
 5   柜台      249 non-null    object 
dtypes: float64(1), int64(1), object(4)
memory usage: 11.8+ KB
df.describe()
Job number transaction amount
count 249.000000 246.000000
mean 1003.469880 1330.313008
std 1.668039 904.300720
min 1001.000000 53.000000
25% 1002.000000 1031.250000
50% 1003.000000 1259.000000
75% 1005.000000 1523.000000
max 1006.000000 12100.000000

- single column selection

If you pursue simplicity and convenience, use . and []; if you pursue consistency and clarity, use loc and iloc

df1['交易额']
姓名
李四     954.0
赵六    1320.0
钱八    1421.0
钱八    1226.0
张三    1442.0
         ...  
李四     859.0
赵六    1668.0
赵六    1722.0
王五    1274.0
钱八     812.0
Name: 交易额, Length: 246, dtype: float64
df1.loc[:,'交易额']
姓名
李四     954.0
赵六    1320.0
钱八    1421.0
钱八    1226.0
张三    1442.0
         ...  
李四     859.0
赵六    1668.0
赵六    1722.0
王五    1274.0
钱八     812.0
Name: 交易额, Length: 246, dtype: float64
df1.交易额
姓名
李四     954.0
赵六    1320.0
钱八    1421.0
钱八    1226.0
张三    1442.0
         ...  
李四     859.0
赵六    1668.0
赵六    1722.0
王五    1274.0
钱八     812.0
Name: 交易额, Length: 246, dtype: float64
df1.iloc[:,3]
姓名
李四     954.0
赵六    1320.0
钱八    1421.0
钱八    1226.0
张三    1442.0
         ...  
李四     859.0
赵六    1668.0
赵六    1722.0
王五    1274.0
钱八     812.0
Name: 交易额, Length: 246, dtype: float64

- Selection of multiple columns

print(df[['姓名','日期','柜台']])
     姓名        日期      柜台
0    张三  2019-03-01    化妆品
1    李四  2019-03-01    化妆品
2    王五  2019-03-01      食品
3    赵六  2019-03-01      食品
4    周七  2019-03-01    日用品
..    ...         ...       ...
244  李四  2019-03-31  蔬菜水果
245  赵六  2019-03-31    日用品
246  赵六  2019-03-31    日用品
247  王五  2019-03-31      食品
248  钱八  2019-03-31      食品

[249 rows x 3 columns]
print(df.loc[:,['姓名','交易额']])
     姓名  交易额
0    张三  1664.0
1    李四   954.0
2    王五  1407.0
3    赵六  1320.0
4    周七   994.0
..    ...     ...
244  李四   859.0
245  赵六  1668.0
246  赵六  1722.0
247  王五  1274.0
248  钱八   812.0

[249 rows x 2 columns]
print(df.iloc[:,0:2])
     工号  姓名
0    1001  张三
1    1002  李四
2    1003  王五
3    1004  赵六
4    1005  周七
..    ...   ...
244  1002  李四
245  1004  赵六
246  1004  赵六
247  1003  王五
248  1006  钱八

[249 rows x 2 columns]

- single line selection

print(df.iloc[5])
工号               1006
姓名               钱八
日期         2019-03-01
时段      14:00-21:00
交易额           1421.0
柜台             日用品
Name: 5, dtype: object

- selection of multiple lines

print(df[5:11])
    工号  姓名        日期           时段  交易额      柜台
5   1006  钱八  2019-03-01  14:00-21:00  1421.0    日用品
6   1006  钱八  2019-03-01   9:00-14:00  1226.0  蔬菜水果
7   1001  张三  2019-03-01  14:00-21:00  1442.0  蔬菜水果
8   1001  张三  2019-03-02   9:00-14:00  1530.0    化妆品
9   1002  李四  2019-03-02  14:00-21:00  1395.0    化妆品
10  1003  王五  2019-03-02   9:00-14:00   936.0      食品
print(df.loc[0:5,:])
   工号  姓名        日期           时段  交易额    柜台
0  1001  张三  2019-03-01   9:00-14:00  1664.0  化妆品
1  1002  李四  2019-03-01  14:00-21:00   954.0  化妆品
2  1003  王五  2019-03-01   9:00-14:00  1407.0    食品
3  1004  赵六  2019-03-01  14:00-21:00  1320.0    食品
4  1005  周七  2019-03-01   9:00-14:00   994.0  日用品
5  1006  钱八  2019-03-01  14:00-21:00  1421.0  日用品
print(df1.iloc[[3,5,10],:])
      工号        日期           时段  交易额      柜台
姓名                                                   
钱八  1006  2019-03-01   9:00-14:00  1226.0  蔬菜水果
张三  1001  2019-03-02   9:00-14:00  1530.0    化妆品
钱八  1006  2019-03-02  14:00-21:00  1141.0    日用品
print(df[['姓名','交易额']])
     姓名  交易额
0    张三  1664.0
1    李四   954.0
2    王五  1407.0
3    赵六  1320.0
4    周七   994.0
..    ...     ...
244  李四   859.0
245  赵六  1668.0
246  赵六  1722.0
247  王五  1274.0
248  钱八   812.0

[249 rows x 2 columns]

- block selection

print(df1.iloc[[3,5,10],[0,1,4]])
      工号        日期      柜台
姓名                            
钱八  1006  2019-03-01  蔬菜水果
张三  1001  2019-03-02    化妆品
钱八  1006  2019-03-02    日用品
print(df[['姓名','日期','柜台']][:5])
   姓名        日期    柜台
0  张三  2019-03-01  化妆品
1  李四  2019-03-01  化妆品
2  王五  2019-03-01    食品
3  赵六  2019-03-01    食品
4  周七  2019-03-01  日用品
print(df.loc[[3,5,10],['姓名','交易额']])
    姓名  交易额
3   赵六  1320.0
5   钱八  1421.0
10  王五   936.0

-- filter rows based on condition (boolean indexing)

Boolean indexing is a method of selecting elements using an array of Boolean values.

print(df[df['交易额']>1700])
     工号  姓名        日期           时段   交易额      柜台
18   1003  王五  2019-03-03   9:00-14:00   1713.0      食品
47   1005  周七  2019-03-06  14:00-21:00   1778.0  蔬菜水果
48   1003  王五  2019-03-07   9:00-14:00   1713.0    化妆品
82   1006  钱八  2019-03-11   9:00-14:00   1737.0      食品
105  1001  张三  2019-03-14   9:00-14:00  12100.0    日用品
113  1002  李四  2019-03-15   9:00-14:00   1798.0    日用品
121  1002  李四  2019-03-16   9:00-14:00   1788.0    日用品
136  1001  张三  2019-03-17  14:00-21:00   1791.0      食品
185  1004  赵六  2019-03-24   9:00-14:00   1775.0    化妆品
188  1002  李四  2019-03-24  14:00-21:00   1793.0  蔬菜水果
205  1001  张三  2019-03-26   9:00-14:00   1746.0    日用品
223  1003  王五  2019-03-28   9:00-14:00   9031.0      食品
227  1005  周七  2019-03-29   9:00-14:00   1737.0  蔬菜水果
246  1004  赵六  2019-03-31  14:00-21:00   1722.0    日用品
print('张三下午班的交易情况')
print(df[df['时段']=='14:00-21:00'][:10])
张三下午班的交易情况
    工号  姓名        日期           时段  交易额      柜台
1   1002  李四  2019-03-01  14:00-21:00   954.0    化妆品
3   1004  赵六  2019-03-01  14:00-21:00  1320.0      食品
5   1006  钱八  2019-03-01  14:00-21:00  1421.0    日用品
7   1001  张三  2019-03-01  14:00-21:00  1442.0  蔬菜水果
9   1002  李四  2019-03-02  14:00-21:00  1395.0    化妆品
11  1004  赵六  2019-03-02  14:00-21:00   906.0      食品
13  1006  钱八  2019-03-02  14:00-21:00  1141.0    日用品
15  1003  王五  2019-03-02  14:00-21:00  1179.0  蔬菜水果
17  1002  李四  2019-03-03  14:00-21:00  1034.0    化妆品
19  1004  赵六  2019-03-03  14:00-21:00  1236.0      食品
print('下午班的交易情况')
print(df[(df.姓名=='张三')&(df.时段=='14:00-21:00')][:10])
下午班的交易情况
     工号  姓名        日期           时段  交易额      柜台
7    1001  张三  2019-03-01  14:00-21:00  1442.0  蔬菜水果
39   1001  张三  2019-03-05  14:00-21:00   856.0  蔬菜水果
73   1001  张三  2019-03-10  14:00-21:00  1040.0    化妆品
91   1001  张三  2019-03-12  14:00-21:00  1435.0      食品
99   1001  张三  2019-03-13  14:00-21:00  1333.0      食品
112  1001  张三  2019-03-14  14:00-21:00  1261.0  蔬菜水果
120  1001  张三  2019-03-15  14:00-21:00  1035.0  蔬菜水果
128  1001  张三  2019-03-16  14:00-21:00  1408.0  蔬菜水果
136  1001  张三  2019-03-17  14:00-21:00  1791.0      食品
144  1001  张三  2019-03-18  14:00-21:00  1378.0      食品
print('张三和李四2人销售总额')
print(df[df['姓名'].isin(['张三','李四'])]['交易额'].sum())
张三和李四2人销售总额
116860.0
print('日用品柜台销售总额')
print(df[df['柜台']=='日用品']['交易额'].sum())
日用品柜台销售总额
88162.0
print('交易额在指定范围内的记录')
print(df[df['交易额'].between(800,850)])
交易额在指定范围内的记录
     工号  姓名        日期           时段  交易额      柜台
41   1002  李四  2019-03-06  14:00-21:00   822.0    化妆品
55   1002  李四  2019-03-07  14:00-21:00   831.0  蔬菜水果
59   1004  赵六  2019-03-08  14:00-21:00   825.0      食品
86   1003  王五  2019-03-11   9:00-14:00   801.0  蔬菜水果
94   1003  王五  2019-03-12   9:00-14:00   831.0  蔬菜水果
106  1002  李四  2019-03-14  14:00-21:00   822.0    日用品
129  1002  李四  2019-03-17   9:00-14:00   828.0    日用品
132  1006  钱八  2019-03-17  14:00-21:00   840.0  蔬菜水果
137  1002  李四  2019-03-18   9:00-14:00   824.0    化妆品
147  1003  王五  2019-03-19   9:00-14:00   846.0  蔬菜水果
152  1001  张三  2019-03-19  14:00-21:00   844.0      食品
160  1001  张三  2019-03-20  14:00-21:00   829.0      食品
163  1006  钱八  2019-03-21   9:00-14:00   807.0  蔬菜水果
233  1001  张三  2019-03-30  14:00-21:00   850.0    化妆品
248  1006  钱八  2019-03-31  14:00-21:00   812.0      食品

- advanced index (multi-level index)

Use the MultiIndex function to create "multi-layer index" midx and "multi-layer columns" mcol.

data=[['电商',101550,176.92,16175610],
['电商',175336,25.95,27113291],
['金融',60348,41.79,10132145],
['金融',36600,196.00,2626634]]
midx=pd.MultiIndex([['中国','美国'],['BABA','JD','GS','MS']],
                    [[0,0,1,1],[0,1,2,3]],
                    names=['地区','代号'])
mcol=pd.MultiIndex([['公司数据','交易数据'],
                        ['行业','雇员','价格','交易量']],
                        [[0,0,1,1],[0,1,2,3]],
                        names=['概括','细分'])
df2=pd.DataFrame(data,index=midx,columns=mcol)
df2
summarize company data transaction data
Segmentation industry employee price Trading volume
area code name
China BABA e-commerce 101550 176.92 16175610
JD e-commerce 175336 25.95 27113291
USA GS finance 60348 41.79 10132145
MS finance 36600 196.00 2626634

The index and columns of this DataFrame have two layers, strictly speaking, it is a four-dimensional data.

df2.loc['中国'].loc['BABA':'JD']
summarize company data transaction data
Segmentation industry employee price Trading volume
code name
BABA e-commerce 101550 176.92 16175610
JD e-commerce 175336 25.95 27113291

- advanced index (adjustment level)

If you don't like the order of index levels, you can adjust them with swaplevel.

df2.swaplevel('地区','代号')
summarize company data transaction data
Segmentation industry employee price Trading volume
code name area
BABA China e-commerce 101550 176.92 16175610
JD China e-commerce 175336 25.95 27113291
GS USA finance 60348 41.79 10132145
MS USA finance 36600 196.00 2626634

If you don't like the order of the columns levels, you can also adjust them with swaplevel.

df2.columns=df.columns.swaplevel(0,1)
df2
Segmentation industry employee price Trading volume
summarize company data company data transaction data transaction data
area code name
China BABA e-commerce 101550 176.92 16175610
JD e-commerce 175336 25.95 27113291
USA GS finance 60348 41.79 10132145
MS finance 36600 196.00 2626634

- advanced index (reset index)

Sometimes, one or more columns of a DataFrame are suitable for index, then set_index can be used to set them as index, if you want to restore the index to columns, then use reset_index.

data={
    
    '地区':['中国','中国','美国','美国'],
'代号':['BABA','JD','MS','GS'],
'行业':['电商','电商','金融','金融'],
'价格':[176.92,25.95,41.79,196.00],
'交易量':[16175610,27113291,10132145,2626634],
'雇员':[101550,175336,60348,36600]}
df3=pd.DataFrame(data)
df3
area code name industry price Trading volume employee
0 China BABA e-commerce 176.92 16175610 101550
1 China JD e-commerce 25.95 27113291 175336
2 USA MS finance 41.79 10132145 60348
3 USA GS finance 196.00 2626634 36600

Set "Region" and "Code Name" as the first-level index and the second-level index.

df4=df3.set_index(['地区','代号'])
df4
industry price Trading volume employee
area code name
China BABA e-commerce 176.92 16175610 101550
JD e-commerce 25.95 27113291 175336
USA MS finance 41.79 10132145 60348
GS finance 196.00 2626634 36600
df5=df3.set_index(['地区','代号'])#将所有index变成columns
df5
industry price Trading volume employee
area code name
China BABA e-commerce 176.92 16175610 101550
JD e-commerce 25.95 27113291 175336
USA MS finance 41.79 10132145 60348
GS finance 196.00 2626634 36600

7.2.3 View data characteristics and statistics

- view data characteristics

1. Use df1.head() and df1.tail(n) to view the n rows of the DataFrame from the beginning or the end. If n is not set, the default value is 5 rows.

df1.head()
Job number date period of time transaction amount counter
Name
Li Si 1002 2019-03-01 14:00-21:00 954.0 cosmetic
Zhao Liu 1004 2019-03-01 14:00-21:00 1320.0 food
money eight 1006 2019-03-01 14:00-21:00 1421.0 daily necessities
money eight 1006 2019-03-01 9:00-14:00 1226.0 蔬菜水果
张三 1001 2019-03-01 14:00-21:00 1442.0 蔬菜水果
df1.tail()
工号 日期 时段 交易额 柜台
姓名
李四 1002 2019-03-31 14:00-21:00 859.0 蔬菜水果
赵六 1004 2019-03-31 9:00-14:00 1668.0 日用品
赵六 1004 2019-03-31 14:00-21:00 1722.0 日用品
王五 1003 2019-03-31 9:00-14:00 1274.0 食品
钱八 1006 2019-03-31 14:00-21:00 812.0 食品
  1. df1.info()
df1.index
Index(['李四', '赵六', '钱八', '钱八', '张三', '张三', '李四', '王五', '赵六',
       '周七',
       ...
       '王五', '钱八', '周七', '李四', '周七', '李四', '赵六', '赵六', '王五',
       '钱八'],
      dtype='object', name='姓名', length=246)
df1.columns
Index(['工号', '日期', '时段', '交易额', '柜台'], dtype='object')
df1.values
array([[1002, '2019-03-01', '14:00-21:00', 954.0, '化妆品'],
       [1004, '2019-03-01', '14:00-21:00', 1320.0, '食品'],
       [1006, '2019-03-01', '14:00-21:00', 1421.0, '日用品'],
       ...,
       [1004, '2019-03-31', '14:00-21:00', 1722.0, '日用品'],
       [1003, '2019-03-31', '9:00-14:00', 1274.0, '食品'],
       [1006, '2019-03-31', '14:00-21:00', 812.0, '食品']], dtype=object)

——统计特征

print('查看交易统计信息')
print(df['交易额'].describe())
查看交易统计信息
count      246.000000
mean      1330.313008
std        904.300720
min         53.000000
25%       1031.250000
50%       1259.000000
75%       1523.000000
max      12100.000000
Name: 交易额, dtype: float64

求某列数据最大值及位置、最小值及位置、最大或者最小几条记录

df1.describe(percentiles=[.2,.75, .8])
工号 交易额
count 246.000000 243.000000
mean 1003.475610 1330.008230
std 1.667644 909.365395
min 1001.000000 53.000000
20% 1002.000000 980.400000
50% 1003.500000 1257.000000
75% 1005.000000 1523.000000
80% 1005.000000 1580.200000
max 1006.000000 12100.000000
print(df['交易额'].sum())
327257.0
print('交易额四分位数')
print(df['交易额'].quantile([0,0.25,0.5,0.75,1]))
交易额四分位数
0.00       53.00
0.25     1031.25
0.50     1259.00
0.75     1523.00
1.00    12100.00
Name: 交易额, dtype: float64
print('交易额中值')
print(df['交易额'].median())
交易额中值
1259.0
print('交易额最小的3条记录')
print(df.nsmallest(3,'交易额'))
交易额最小的3条记录
     工号  姓名        日期           时段  交易额    柜台
76   1005  周七  2019-03-10   9:00-14:00    53.0  日用品
97   1002  李四  2019-03-13  14:00-21:00    98.0  日用品
194  1001  张三  2019-03-25  14:00-21:00   114.0  化妆品
print('交易额最大的5条记录')
print(df.nlargest(5,'交易额'))
交易额最大的5条记录
     工号  姓名        日期           时段   交易额      柜台
105  1001  张三  2019-03-14   9:00-14:00  12100.0    日用品
223  1003  王五  2019-03-28   9:00-14:00   9031.0      食品
113  1002  李四  2019-03-15   9:00-14:00   1798.0    日用品
188  1002  李四  2019-03-24  14:00-21:00   1793.0  蔬菜水果
136  1001  张三  2019-03-17  14:00-21:00   1791.0      食品
print('最后一个日期')
print(df['日期'].max())
最后一个日期
2019-03-31
print('最小的工号')
print(df['工号'].min())
最小的工号
1001
print('第一个最小交易额的行下标')
index=df['交易额'].idxmin()
print(index)
第一个最小交易额的行下标
76
print('第一个最小交易额')
print(df.loc[index,'交易额'])
第一个最小交易额
53.0
print('第一个最大交易额的行下标')
index=df['交易额'].idxmax()
print(index)
第一个最大交易额的行下标
105
print('第一个最大的交易额')
print(df.loc[index,'交易额'])
第一个最大的交易额
12100.0

7.2.4按不同标准对数据排序

——sort_values()

DataFrame.sort_values(by=‘’, axis=0, ascending=True, inplace=False, kind=‘quicksort’, na_position=‘last’, ignore_index=False, key=None)

by:指定要进行排序的列名或索引值

axis:若 axis=0 或 ‘index’,则按照指定 列 的数据大小排序;若 axis=1 或 ‘columns’,则按照指定 索引 中数据大小排序。默认axis=0

ascending:若 ascending=True,则按照升序排序;若 ascending=False,则按降序排序,默认为True,即升序排序。如果这是一个 bool 列表,则必须匹配 by 的长度

inplace:排序后的数据是否替换原来的数据,默认为False,即不替换

ignore_index:是否重置索引,默认为不重置

import pandas as pd

pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df=pd.read_excel(r'超市营业额2.xlsx')

print('按交易额和工号降序排序')
print(df.sort_values(by=['交易额','工号'],ascending=False)[:12])
按交易额和工号降序排序
     工号  姓名        日期           时段   交易额      柜台
105  1001  张三  2019-03-14   9:00-14:00  12100.0    日用品
223  1003  王五  2019-03-28   9:00-14:00   9031.0      食品
113  1002  李四  2019-03-15   9:00-14:00   1798.0    日用品
188  1002  李四  2019-03-24  14:00-21:00   1793.0  蔬菜水果
136  1001  张三  2019-03-17  14:00-21:00   1791.0      食品
121  1002  李四  2019-03-16   9:00-14:00   1788.0    日用品
47   1005  周七  2019-03-06  14:00-21:00   1778.0  蔬菜水果
185  1004  赵六  2019-03-24   9:00-14:00   1775.0    化妆品
205  1001  张三  2019-03-26   9:00-14:00   1746.0    日用品
82   1006  钱八  2019-03-11   9:00-14:00   1737.0      食品
227  1005  周七  2019-03-29   9:00-14:00   1737.0  蔬菜水果
246  1004  赵六  2019-03-31  14:00-21:00   1722.0    日用品
print('按交易额降序、工号升序排序')
print(df.sort_values(by=['交易额','工号'],ascending=[False,True])[:12])
按交易额降序、工号升序排序
     工号  姓名        日期           时段   交易额      柜台
105  1001  张三  2019-03-14   9:00-14:00  12100.0    日用品
223  1003  王五  2019-03-28   9:00-14:00   9031.0      食品
113  1002  李四  2019-03-15   9:00-14:00   1798.0    日用品
188  1002  李四  2019-03-24  14:00-21:00   1793.0  蔬菜水果
136  1001  张三  2019-03-17  14:00-21:00   1791.0      食品
121  1002  李四  2019-03-16   9:00-14:00   1788.0    日用品
47   1005  周七  2019-03-06  14:00-21:00   1778.0  蔬菜水果
185  1004  赵六  2019-03-24   9:00-14:00   1775.0    化妆品
205  1001  张三  2019-03-26   9:00-14:00   1746.0    日用品
227  1005  周七  2019-03-29   9:00-14:00   1737.0  蔬菜水果
82   1006  钱八  2019-03-11   9:00-14:00   1737.0      食品
246  1004  赵六  2019-03-31  14:00-21:00   1722.0    日用品
print('按工号升序排序')
print(df.sort_values(by='工号',na_position='last')[:10])
按工号升序排序
     工号  姓名        日期           时段  交易额      柜台
0    1001  张三  2019-03-01   9:00-14:00  1664.0    化妆品
178  1001  张三  2019-03-23  14:00-21:00  1271.0    化妆品
39   1001  张三  2019-03-05  14:00-21:00   856.0  蔬菜水果
40   1001  张三  2019-03-06   9:00-14:00  1037.0    化妆品
177  1001  张三  2019-03-23   9:00-14:00  1296.0    化妆品
169  1001  张三  2019-03-22   9:00-14:00   946.0    化妆品
160  1001  张三  2019-03-20  14:00-21:00   829.0      食品
54   1001  张三  2019-03-07   9:00-14:00  1263.0  蔬菜水果
157  1001  张三  2019-03-20   9:00-14:00  1037.0    日用品
225  1001  张三  2019-03-29  14:00-21:00  1523.0    化妆品

——sort.index()

DataFrame.sort_index(axis=0, level=None, ascending=True, inplace=False, kind=’quicksort’, na_position=’last’, sort_remaining=True, by=None)

axis:索引,直接排序的列

level:如果不是,则对指定索引级别的值进行排序

ascending:升序与降序排序

inplace:如果为True,则就地执行操作

kind:{“快速排序”,“合并排序”,“堆排序”},默认为“快速排序”。选择排序算法。有关更多信息,另请参见ndarray.np.sort。 mergesort是唯一稳定的算法。对于DataFrame,此选项仅在对单个列或标签进行排序时适用。

print('按列名升序排序')
print(df.sort_index(axis=1,ascending=True)[:10])
按列名升序排序
   交易额  姓名  工号        日期           时段      柜台
0  1664.0  张三  1001  2019-03-01   9:00-14:00    化妆品
1   954.0  李四  1002  2019-03-01  14:00-21:00    化妆品
2  1407.0  王五  1003  2019-03-01   9:00-14:00      食品
3  1320.0  赵六  1004  2019-03-01  14:00-21:00      食品
4   994.0  周七  1005  2019-03-01   9:00-14:00    日用品
5  1421.0  钱八  1006  2019-03-01  14:00-21:00    日用品
6  1226.0  钱八  1006  2019-03-01   9:00-14:00  蔬菜水果
7  1442.0  张三  1001  2019-03-01  14:00-21:00  蔬菜水果
8  1530.0  张三  1001  2019-03-02   9:00-14:00    化妆品
9  1395.0  李四  1002  2019-03-02  14:00-21:00    化妆品

7.2.5 使用分组与聚合对员工业绩进行汇总

groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs)

参数by用来指定作用于index的函数、字典、Series对象,或者指定列名作为分组依据;

参数as_index=False时用来分组的列中的数据不作为结果DataFrame对象的index;

参数squeeze=True时会在可能的情况下降低结果对象的维度。

print('指定by参数为字典')
print(df.groupby(by={
    
    7:'下标为7的行', 
                     35:'下标为35的行'})['交易额'].sum())
指定by参数为字典
下标为35的行     974.0
下标为7的行     1442.0
Name: 交易额, dtype: float64
print('不同时段的销售总额')
print(df.groupby(by='时段')['交易额'].sum()) 
不同时段的销售总额
时段
14:00-21:00    151228.0
9:00-14:00     176029.0
Name: 交易额, dtype: float64
print('各柜台的销售总额')
print(df.groupby(by='柜台')['交易额'].sum())
各柜台的销售总额
柜台
化妆品      75389.0
日用品      88162.0
蔬菜水果    78532.0
食品        85174.0
Name: 交易额, dtype: float64
#可以查看每个员工上班总时长是否均匀 
print('每个员工上班的次数')
dff=df.groupby(by='姓名')['日期'].count()
dff.name ='上班次数' 
print(dff) 
每个员工上班的次数
姓名
周七    42
张三    38
李四    47
王五    40
赵六    45
钱八    37
Name: 上班次数, dtype: int64
print('汇总交易额转换为整数')
print(df.groupby(by='姓名').sum()['交易额'].apply(int))
汇总交易额转换为整数
姓名
周七    47818
张三    58130
李四    58730
王五    58892
赵六    56069
钱八    47618
Name: 交易额, dtype: int64
print('每个员工交易额的史值') 
dff=df.groupby(by='姓名').median() 
print(dff['交易额'])
每个员工交易额的史值
姓名
周七    1134.5
张三    1290.0
李四    1276.0
王五    1227.0
赵六    1224.0
钱八    1381.0
Name: 交易额, dtype: float64
dff['排名'] = dff['交易额'].rank(ascending=False)
print('每个员工交易额中值的排名') 
print(dff[['交易额','排名']])
每个员工交易额中值的排名
      交易额  排名
姓名              
周七  1134.5   6.0
张三  1290.0   2.0
李四  1276.0   3.0
王五  1227.0   4.0
赵六  1224.0   5.0
钱八  1381.0   1.0
print('每个员工不同时段的交易额') 
print(df.groupby(by=['姓名','时段'])['交易额'].sum()) 
每个员工不同时段的交易额
姓名  时段       
周七  14:00-21:00    15910.0
      9:00-14:00     31908.0
张三  14:00-21:00    23659.0
      9:00-14:00     34471.0
李四  14:00-21:00    32295.0
      9:00-14:00     26435.0
王五  14:00-21:00    17089.0
      9:00-14:00     41803.0
赵六  14:00-21:00    29121.0
      9:00-14:00     26948.0
钱八  14:00-21:00    33154.0
      9:00-14:00     14464.0
Name: 交易额, dtype: float64
#对不同的列可以采用不同的函数 
print('时段和交易额采用不同的聚合方式')
print(df.groupby(by=['姓名'])['时段','交易额'].aggregate({
    
    '交易额':np.sum,
                                                   '时段':lambda x:'各时段累计'}))
时段和交易额采用不同的聚合方式
       交易额        时段
姓名                     
周七  47818.0  各时段累计
张三  58130.0  各时段累计
李四  58730.0  各时段累计
王五  58892.0  各时段累计
赵六  56069.0  各时段累计
钱八  47618.0  各时段累计
#使用DataErame结构的agg()方法对指定列进行聚合 
print('使用agg()方法对交易额进行聚合') 
print(df.agg({
    
    '交易额':['sum','mean','min','max','median'],
              '日期':['min','max']})) 
使用agg()方法对交易额进行聚合
               交易额        日期
sum     327257.000000         NaN
mean      1330.313008         NaN
min         53.000000  2019-03-01
max      12100.000000  2019-03-31
median    1259.000000         NaN
print('对分组结果进行聚合')
print('查看分组聚合后的部分结果')
print(df.groupby(by='姓名').agg(['max','min', 'mean', 'median'])['交易额'])
对分组结果进行聚合
查看分组聚合后的部分结果
          max    min         mean  median
姓名                                     
周七   1778.0   53.0  1195.450000  1134.5
张三  12100.0  114.0  1529.736842  1290.0
李四   1798.0   98.0  1249.574468  1276.0
王五   9031.0  801.0  1472.300000  1227.0
赵六   1775.0  825.0  1245.977778  1224.0
钱八   1737.0  807.0  1322.722222  1381.0

7.2.6 数据的异常值处理

异常值是指严重超出正常范围的数值,这样的数据一般是数据采集错误或类似原因引起的。

在数据分析时,需要把这些数据删除或替换为特定的值(例如人为设定的正常范围边界值),减小对最终数据分析结果的影响。

异常值处理的关键是根据实际情况准确定义正常范围边界值,超出正常范围的数值认为是异常值。

1.基于统计与数据发布 2.箱形图分析

print('查看交易额低于200的数据')
print(df[df.交易额<200])
查看交易额低于200的数据
     工号  姓名        日期           时段  交易额    柜台
76   1005  周七  2019-03-10   9:00-14:00    53.0  日用品
97   1002  李四  2019-03-13  14:00-21:00    98.0  日用品
194  1001  张三  2019-03-25  14:00-21:00   114.0  化妆品
df.loc[df.交易额<200,'交易额'] = df[df.交易额<200]['交易额'].map(lambda num:num*1.5)
print('上浮50%之后仍低于200的数据')
print(df[df.交易额<200])
上浮50%之后仍低于200的数据
     工号  姓名        日期           时段  交易额    柜台
76   1005  周七  2019-03-10   9:00-14:00    79.5  日用品
97   1002  李四  2019-03-13  14:00-21:00   147.0  日用品
194  1001  张三  2019-03-25  14:00-21:00   171.0  化妆品
print('查看交易额高于3000的数据')
print(df[df['交易额']>3000])
查看交易额高于3000的数据
     工号  姓名        日期          时段   交易额    柜台
105  1001  张三  2019-03-14  9:00-14:00  12100.0  日用品
223  1003  王五  2019-03-28  9:00-14:00   9031.0    食品
print('交易额低于200或高于3000的数据') 
print(df[(df.交易额<200)|(df.交易额>3000)]) 
交易额低于200或高于3000的数据
     工号  姓名        日期           时段   交易额    柜台
76   1005  周七  2019-03-10   9:00-14:00     79.5  日用品
97   1002  李四  2019-03-13  14:00-21:00    147.0  日用品
105  1001  张三  2019-03-14   9:00-14:00  12100.0  日用品
194  1001  张三  2019-03-25  14:00-21:00    171.0  化妆品
223  1003  王五  2019-03-28   9:00-14:00   9031.0    食品
#把低于200的交易额都替换为固定的200 
df.loc[df.交易额<200,'交易额']=200 
print('交易额低于200或高于3000的数据') 
print(df[(df.交易额<200)|(df.交易额>3000)]) 
交易额低于200或高于3000的数据
     工号  姓名        日期          时段   交易额    柜台
105  1001  张三  2019-03-14  9:00-14:00  12100.0  日用品
223  1003  王五  2019-03-28  9:00-14:00   9031.0    食品
 #把高于3000的交易额都替换为固定的3000 
df.loc[df.交易额>3000,'交易额']=3000 
print('交易额低于200或高于3000的数量')
print(df[(df.交易额<200)|(df.交易额>3000)]['交易额'].count())
交易额低于200或高于3000的数量
0

7.2.7处理超市交易额数据中的缺失值

dropna(axis=0, how=‘any’, thresh=None, subset=None, inplace=False)

参数how='any’时表示只要某行包含缺失值就丢弃,how='all’时表示某行全部为缺失值才丢弃;

参数thresh用来指定保留包含几个非缺失值数据的行;

参数subset用来指定在判断缺失值时只考虑哪些列。

fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None, **kwargs)

参数value用来指定要替换的值,可以是标量、字典、Series或DataFrame;

参数method用来指定填充缺失值的方式,值为’pad’或’ffill’时表示使用扫描过程中遇到的最后一个有效值一直填充到下一个有效值,值为’backfill’或’bfill’时表示使用缺失值之后遇到的第一个有效值填充前面遇到的所有连续缺失值;

参数limit用来指定设置了参数method时最多填充多少个连续的缺失值;

参数inplace=True时表示原地替换,inplace=False时返回一个新的DataFrame对象而不对原来的DataFrame做任何修改。

from copy import deepcopy

pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df=pd.read_excel(r'超市营业额2.xlsx')
print('数据总行数')
print(len(df))
数据总行数
249
print('丢失缺失值之后的行数')
print(len(df.dropna()))
丢失缺失值之后的行数
246
print('包含缺失值的行')
print(df[df['交易额'].isnull()])
包含缺失值的行
     工号  姓名        日期           时段  交易额    柜台
110  1005  周七  2019-03-14  14:00-21:00     NaN  化妆品
124  1006  钱八  2019-03-16  14:00-21:00     NaN    食品
168  1005  周七  2019-03-21  14:00-21:00     NaN    食品
print('使用固定值替换缺失值')
dff=deepcopy(df)
dff.loc[dff.交易额.isnull(),'交易额']=1000
print(dff.iloc[[110,124,168],:])
使用固定值替换缺失值
     工号  姓名        日期           时段  交易额    柜台
110  1005  周七  2019-03-14  14:00-21:00  1000.0  化妆品
124  1006  钱八  2019-03-16  14:00-21:00  1000.0    食品
168  1005  周七  2019-03-21  14:00-21:00  1000.0    食品
print('使用每人交易额均值替换缺失值')
dff=deepcopy(df)
for i in dff[dff.交易额.isnull()].index:
    dff.loc[i,'交易额']=round(dff.loc[dff.姓名==dff.loc[i,'姓名'],'交易额'].mean())
print(dff.iloc[[110,124,168],:])
使用每人交易额均值替换缺失值
     工号  姓名        日期           时段  交易额    柜台
110  1005  周七  2019-03-14  14:00-21:00  1195.0  化妆品
124  1006  钱八  2019-03-16  14:00-21:00  1323.0    食品
168  1005  周七  2019-03-21  14:00-21:00  1195.0    食品
print('使用整体均值的80%填充')
df.fillna({
    
    '交易额':round(df['交易额'].mean()*0.8)},inplace=True)
print(df.iloc[[110,124,168],:])
使用整体均值的80%填充
     工号  姓名        日期           时段  交易额    柜台
110  1005  周七  2019-03-14  14:00-21:00  1064.0  化妆品
124  1006  钱八  2019-03-16  14:00-21:00  1064.0    食品
168  1005  周七  2019-03-21  14:00-21:00  1064.0    食品

7.2.8处理超市交易数据中的重复值

duplicated(subset=None, keep=‘first’)

参数subset用来指定判断不同行的数据是否重复时所依据的一列或多列,默认使用整行所有列的数据进行比较;

参数keep='first’时表示重复数据的第一次出现标记为False,keep='last’时表示重复数据的最后一次出现标记为False,keep=False时表示标记所有重复数据为True。

drop_duplicates(subset=None, keep=‘first’, inplace=False)

参数subset和keep的含义与duplicated()方法类似;

参数inplace=True时表示原地修改,此时duplicated()方法没有返回值,inplace=False时表示返回新的DataFrame结构而不对原来的DataFrame做任何修改。

from copy import deepcopy
import pandas as pd
import numpy as np
pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)
df=pd.read_excel(r'超市营业额2.xlsx')
print('数据总行数')
print(len(df))
数据总行数
249
print('数据总行数')
print(len(df))
数据总行数
249
print('一人同时负责多个柜台的排班')
dff=df[['工号','姓名','日期','时段']]
dff=dff[dff.duplicated()]
for row in dff.values:
    print(df[ (df.工号==row[0]) & (df.日期==row[2]) & (df.日期==row[2]) &(df.时段==row[3])])
一人同时负责多个柜台的排班
    工号  姓名        日期           时段  交易额      柜台
49  1002  李四  2019-03-07  14:00-21:00  1199.0    化妆品
55  1002  李四  2019-03-07  14:00-21:00   831.0  蔬菜水果
     工号  姓名        日期           时段  交易额      柜台
103  1006  钱八  2019-03-13  14:00-21:00  1609.0  蔬菜水果
104  1006  钱八  2019-03-13  14:00-21:00  1609.0  蔬菜水果
     工号  姓名        日期          时段  交易额      柜台
171  1006  钱八  2019-03-22  9:00-14:00  1555.0  蔬菜水果
175  1006  钱八  2019-03-22  9:00-14:00  1503.0      食品
     工号  姓名        日期          时段  交易额    柜台
201  1004  赵六  2019-03-26  9:00-14:00  1599.0  化妆品
210  1004  赵六  2019-03-26  9:00-14:00  1257.0  化妆品
#直接丢弃全部行
df = df.drop_duplicates()
print('有效数据总行')
print(len(df))
有效数据总行
248
#可以查看是否有录入错误的工号和姓名
print('所有工号与姓名的对应关系')
dff = df[['工号','姓名']]
print(dff.drop_duplicates())
所有工号与姓名的对应关系
   工号  姓名
0  1001  张三
1  1002  李四
2  1003  王五
3  1004  赵六
4  1005  周七
5  1006  钱八

7.2.9使用数据差分查看员工业绩波动情况

diff(periods=1, axis=0)

参数periods用来指定差分的跨度,当periods=1且axis=0时表示每一行数据减去紧邻的上一行数据,当periods=2且axis=0时表示每一行减去上面第二行的数据;

参数axis=0时表示按行进行纵向差分,axis=1时表示按列横向差分。

import pandas as pd

pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df = pd.read_excel(r'超市营业额2.xlsx')

print('每天交易总额变化情况')
dff = df.groupby(by='日期').sum()['交易额'].diff()
print(dff.map(lambda num:'%+.2f'%num)[:5])
每天交易总额变化情况
日期
2019-03-01       +nan
2019-03-02    -248.00
2019-03-03    +924.00
2019-03-04     +56.00
2019-03-05    -277.00
Name: 交易额, dtype: object
print('张三的每天交易总额变化情况')
print(df[df.姓名=='张三'].groupby(by='日期').sum()['交易额'].diff()[:5])
张三的每天交易总额变化情况
日期
2019-03-01       NaN
2019-03-02   -1576.0
2019-03-03    -169.0
2019-03-04    -145.0
2019-03-05    1031.0
Name: 交易额, dtype: float64

7.2.10使用透视表与交叉表查看业绩汇总数据

——透视表

pivot(index=None, columns=None, values=None)

参数index用来指定使用哪一列数据作为结果DataFrame的索引;

参数columns用来指定哪一列数据作为结果DataFrame的列名;

参数values用来指定哪一列数据作为结果DataFrame的值。

pivot_table(values=None, index=None, columns=None, aggfunc=‘mean’, fill_value=None, margins=False, dropna=True, margins_name=‘All’)

参数values、index、columns的含义与DataFrame结构的pivot()方法一样;

参数aggfunc用来指定数据的聚合方式,例如求平均、求和、求中值等;

参数margins用来指定是否显示边界以及边界上的数据;

参数margins_name用来指定边界数据的索引名称和列名;

参数dropna用来指定是否丢弃缺失值。

import pandas as pd

pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df = pd.read_excel(r'超市营业额2.xlsx')

print('查看每人每天交易总额')
dff = df.groupby(by=['姓名','日期'],as_index=False).sum()
print(dff.iloc[:,:5])
查看每人每天交易总额
     姓名        日期  工号  交易额
0    周七  2019-03-01  1005   994.0
1    周七  2019-03-02  1005  1444.0
2    周七  2019-03-03  2010  3230.0
3    周七  2019-03-04  2010  2545.0
4    周七  2019-03-05  1005  1249.0
..    ...         ...   ...     ...
173  钱八  2019-03-27  2012  2996.0
174  钱八  2019-03-28  1006  1219.0
175  钱八  2019-03-29  1006  1639.0
176  钱八  2019-03-30  1006  1090.0
177  钱八  2019-03-31  1006   812.0

[178 rows x 4 columns]
print('交易总额低于5万元的员工前5天业绩')
print(dff[dff.sum(axis=1)<50000].iloc[:,:5])
交易总额低于5万元的员工前5天业绩
     姓名        日期  工号  交易额
0    周七  2019-03-01  1005   994.0
1    周七  2019-03-02  1005  1444.0
2    周七  2019-03-03  2010  3230.0
3    周七  2019-03-04  2010  2545.0
4    周七  2019-03-05  1005  1249.0
..    ...         ...   ...     ...
173  钱八  2019-03-27  2012  2996.0
174  钱八  2019-03-28  1006  1219.0
175  钱八  2019-03-29  1006  1639.0
176  钱八  2019-03-30  1006  1090.0
177  钱八  2019-03-31  1006   812.0

[178 rows x 4 columns]
print('交易总额低于5万元的员工姓名')
print(dff[dff.sum(axis=1)<50000].index.values)
交易总额低于5万元的员工姓名
[  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17
  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35
  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53
  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71
  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89
  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107
 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177]
print('使用pivot_table()方法实现')
print(df.pivot_table(values='交易额',index='姓名',columns='日期',aggfunc='sum',margins=True).iloc[:,:5])
使用pivot_table()方法实现
日期  2019-03-01  2019-03-02  2019-03-03  2019-03-04  2019-03-05
姓名                                                            
周七       994.0      1444.0      3230.0      2545.0      1249.0
张三      3106.0      1530.0      1361.0      1216.0      2247.0
李四       954.0      3044.0      1034.0      2734.0      3148.0
王五      1407.0      2115.0      1713.0      1590.0      1687.0
赵六      1320.0       906.0      2309.0      1673.0       974.0
钱八      2647.0      1141.0      1457.0      1402.0      1578.0
All      10428.0     10180.0     11104.0     11160.0     10883.0
print('查看每人在柜台的交易额')
dff = df.groupby(by=['姓名','柜台'],as_index=False).sum()
print(df.pivot_table(values='交易额',index='姓名',columns='日期',aggfunc='count',margins=True).iloc[:,:5])
查看每人在柜台的交易额
日期  2019-03-01  2019-03-02  2019-03-03  2019-03-04  2019-03-05
姓名                                                            
周七         1.0         1.0         2.0         2.0         1.0
张三         2.0         1.0         1.0         1.0         2.0
李四         1.0         2.0         1.0         2.0         2.0
王五         1.0         2.0         1.0         1.0         1.0
赵六         1.0         1.0         2.0         1.0         1.0
钱八         2.0         1.0         1.0         1.0         1.0
All          8.0         8.0         8.0         8.0         8.0
print('查看每人在各柜台的上班次数')
print(df.pivot_table(values='交易额',index='姓名',columns='柜台',aggfunc='count',margins=True))
查看每人在各柜台的上班次数
柜台  化妆品  日用品  蔬菜水果  食品  All
姓名                                     
周七     8.0    11.0      14.0   7.0   40
张三    19.0     6.0       6.0   7.0   38
李四    16.0     9.0      18.0   4.0   47
王五     8.0     9.0       9.0  14.0   40
赵六    10.0    18.0       2.0  15.0   45
钱八     NaN     9.0      14.0  13.0   36
All     61.0    62.0      63.0  60.0  246

——交叉表

交叉表是一种特殊的透视表,往往用来统计频次,也可以使用参数aggfunc指定聚合函数实现其他功能。

crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, dropna=True, normalize=False)

参数values、index、columns的含义与DataFrame结构的pivot()方法一样;

参数aggfunc用来指定聚合函数,默认为统计次数;

参数rownames和colnames分别用来指定行索引和列索引的名字,如果不指定则直接使用参数index和columns指定的列名。

import pandas as pd

pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df = pd.read_excel(r'超市营业额2.xlsx')

print('每人每天的上班次数')
print(pd.crosstab(df.姓名,df.日期,margins=True).iloc[:,:5])
每人每天的上班次数
日期  2019-03-01  2019-03-02  2019-03-03  2019-03-04  2019-03-05
姓名                                                            
周七           1           1           2           2           1
张三           2           1           1           1           2
李四           1           2           1           2           2
王五           1           2           1           1           1
赵六           1           1           2           1           1
钱八           2           1           1           1           1
All            8           8           8           8           8
print('每人在各柜台上班总次数')
print(pd.crosstab(df.姓名,df.柜台,margins=True).iloc[:,:5])
每人在各柜台上班总次数
柜台  化妆品  日用品  蔬菜水果  食品  All
姓名                                     
周七       9      11        14     8   42
张三      19       6         6     7   38
李四      16       9        18     4   47
王五       8       9         9    14   40
赵六      10      18         2    15   45
钱八       0       9        14    14   37
All       62      62        63    62  249
print('每人在各柜台交易总额')
print(pd.crosstab(df.姓名,df.柜台,df.交易额,aggfunc='sum'))
每人在各柜台交易总额
柜台   化妆品   日用品  蔬菜水果     食品
姓名                                     
周七   9516.0  12863.0   16443.0   8996.0
张三  22975.0  18629.0    7265.0   9261.0
李四  20467.0  10104.0   23263.0   4896.0
王五  10112.0  11357.0   10473.0  26950.0
赵六  12319.0  23286.0    2527.0  17937.0
钱八      NaN  11923.0   18561.0  17134.0
print('每人在各柜台交易额平均值')
print(pd.crosstab(df.姓名,df.柜台,df.交易额,aggfunc='mean').apply(lambda num:round(num,2)))
每人在各柜台交易额平均值
柜台   化妆品   日用品  蔬菜水果     食品
姓名                                     
周七  1189.50  1169.36   1174.50  1285.14
张三  1209.21  3104.83   1210.83  1323.00
李四  1279.19  1122.67   1292.39  1224.00
王五  1264.00  1261.89   1163.67  1925.00
赵六  1231.90  1293.67   1263.50  1195.80
钱八      NaN  1324.78   1325.79  1318.00

7.2.11使用重采样技术按时间段查看员工业绩

resample(rule, how=None, axis=0, fill_method=None, closed=None, label=None, convention=‘start’, kind=None, loffset=None, limit=None, base=0, on=None, level=None)

参数rule用来指定重采样的时间间隔,例如’7D’表示每7天采样一次;

参数how用来指定如何处理两个采样时间之间的数据,不过该参数很快会被新版本丢弃不用了;

参数label = 'left’表示使用采样周期的起始时间作为结果DataFrame的index,label='right’表示使用采样周期的结束时间作为结果DataFrame的index;

参数on用来指定根据哪一列进行重采样,要求该列数据为日期时间类型。

import numpy as np
import pandas as pd
df = pd.read_excel(r'超市营业额2.xlsx')
df.日期 = pd.to_datetime(df.日期)
print('每7天营业额')
print(df.resample('7D',on='日期',label='right').sum()['交易额'])
每7天营业额
日期
2019-03-08    73600.0
2019-03-15    77823.0
2019-03-22    65996.0
2019-03-29    79046.0
2019-04-05    30792.0
Freq: 7D, Name: 交易额, dtype: float64
print('每7天营业总额')
print(df.resample('7D',on='日期').sum()['交易额'])
每7天营业总额
日期
2019-03-01    73600.0
2019-03-08    77823.0
2019-03-15    65996.0
2019-03-22    79046.0
2019-03-29    30792.0
Freq: 7D, Name: 交易额, dtype: float64
print('每7天营业额平均值')
func = lambda num:round(num,2)
print(df.resample('7D',on='日期',label='right').mean().apply(func)['交易额'])
每7天营业额平均值
日期
2019-03-08    1314.29
2019-03-15    1389.70
2019-03-22    1222.15
2019-03-29    1411.54
2019-04-05    1283.00
Freq: 7D, Name: 交易额, dtype: float64

7.2.12多索引相关技术与操作

DataFrame结构支持多个索引,既可以在读取数据时使用index_col指定多列,也可以通过groupby()方法分组时指定多个索引。对于含有多个索引的DataFrame结构,在使用sort_index()方法按索引排序、使用groupby()方法进行分组时,都可以使用参数level指定按哪一级索引进行排序或分组。

import numpy as np
import pandas as pd

#设置输出结果对齐方式
pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df = pd.read_excel(r'超市营业额2.xlsx')
 #删除工号一列的数据 
df.drop('工号',axis=1,inplace=True)
df = df.groupby(by=['姓名','柜台']).sum()
print('按姓名和柜台进行分组汇总')
print(df[:10])
按姓名和柜台进行分组汇总
                交易额
姓名 柜台             
周七 化妆品     9516.0
     日用品    12863.0
     蔬菜水果  16443.0
     食品       8996.0
张三 化妆品    22975.0
     日用品    18629.0
     蔬菜水果   7265.0
     食品       9261.0
李四 化妆品    20467.0
     日用品    10104.0
print('查看周七的汇总数据')
print(df.loc['周七','化妆品'])
查看周七的汇总数据
交易额    9516.0
Name: (周七, 化妆品), dtype: float64
print('查看周七在化妆品柜台的交易数据')
print(df.loc[('周七','化妆品')])
查看周七在化妆品柜台的交易数据
交易额    9516.0
Name: (周七, 化妆品), dtype: float64
import numpy as np
import pandas as pd

#设置输出结果对齐方式
pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df = pd.read_excel(r'超市营业额2.xlsx')
 #删除工号一列的数据 
df.drop('工号',axis=1,inplace=True)
#按索引“柜台”排序,查看前12行
dff = df.sort_index(level='柜台',axis=0)
print('按柜台排序,查看前12行')
print(dff[:12])
按柜台排序,查看前12行
    姓名        日期           时段  交易额      柜台
0   张三  2019-03-01   9:00-14:00  1664.0    化妆品
1   李四  2019-03-01  14:00-21:00   954.0    化妆品
2   王五  2019-03-01   9:00-14:00  1407.0      食品
3   赵六  2019-03-01  14:00-21:00  1320.0      食品
4   周七  2019-03-01   9:00-14:00   994.0    日用品
5   钱八  2019-03-01  14:00-21:00  1421.0    日用品
6   钱八  2019-03-01   9:00-14:00  1226.0  蔬菜水果
7   张三  2019-03-01  14:00-21:00  1442.0  蔬菜水果
8   张三  2019-03-02   9:00-14:00  1530.0    化妆品
9   李四  2019-03-02  14:00-21:00  1395.0    化妆品
10  王五  2019-03-02   9:00-14:00   936.0      食品
11  赵六  2019-03-02  14:00-21:00   906.0      食品
#按索引“姓名”排序,查看前12行
dff = df.sort_index(level='柜台',axis=0)
print('按姓名排序,查看前12行')
print(dff[:12])
按姓名排序,查看前12行
    姓名        日期           时段  交易额      柜台
0   张三  2019-03-01   9:00-14:00  1664.0    化妆品
1   李四  2019-03-01  14:00-21:00   954.0    化妆品
2   王五  2019-03-01   9:00-14:00  1407.0      食品
3   赵六  2019-03-01  14:00-21:00  1320.0      食品
4   周七  2019-03-01   9:00-14:00   994.0    日用品
5   钱八  2019-03-01  14:00-21:00  1421.0    日用品
6   钱八  2019-03-01   9:00-14:00  1226.0  蔬菜水果
7   张三  2019-03-01  14:00-21:00  1442.0  蔬菜水果
8   张三  2019-03-02   9:00-14:00  1530.0    化妆品
9   李四  2019-03-02  14:00-21:00  1395.0    化妆品
10  王五  2019-03-02   9:00-14:00   936.0      食品
11  赵六  2019-03-02  14:00-21:00   906.0      食品
#按索引“柜台”分组求和
print('按柜台分组求和')
dfff = dff.groupby(by='柜台').sum() 
dfff.columns = ['交易额总和']
print(dfff)
按柜台分组求和
          交易额总和
柜台                
化妆品       75389.0
日用品       88162.0
蔬菜水果     78532.0
食品         85174.0
#按索引“姓名”分组求中值
print('按姓名分组求中值')
dfff = dff.groupby(by='姓名').median() 
dfff.columns = ['交易额中值']
print(dfff)
按姓名分组求中值
      交易额中值
姓名            
周七      1134.5
张三      1290.0
李四      1276.0
王五      1227.0
赵六      1224.0
钱八      1381.0

7.2.13 使用标准差与协方差分析员工业绩

import numpy as np
import pandas as pd

#设置输出结果对齐方式
pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df = pd.read_excel(r'超市营业额2.xlsx')
#丢弃缺失值和重复值
df.dropna(inplace=True)
df.drop_duplicates(inplace=True)
#处理缺失值
df.loc[df.交易额<200,'交易额'] = 200
df.loc[df.交易额>3000,'交易额'] = 3000
#使用交叉表得到不同员工在不同柜台的交易额平均值
dff = pd.crosstab(df.姓名,df.柜台,df.交易额,aggfunc='mean')
print('标准差')
print(dff.std())
标准差
柜台
化妆品       36.480497
日用品      159.008839
蔬菜水果     60.331171
食品        105.031231
dtype: float64
print('协方差')
print(dff.cov())
协方差
柜台           化妆品        日用品     蔬菜水果          食品
柜台                                                          
化妆品    1330.826697  -2296.460562   923.019793    692.300017
日用品   -2296.460562  25283.810853 -1030.111953   2957.850772
蔬菜水果   923.019793  -1030.111953  3639.850206  -3918.549524
食品       692.300017   2957.850772 -3918.549524  11031.559490

7.2.14 使用pandas的属性接口实现高级功能

DataFrame数据中的日期时间列支持dt接口,该接口提供了dayofweek、dayofyear、is_leap_year、quarter、weekday_name等属性和方法,例如quarter可以直接得到每个日期分别是第几个季度,weekday_name可以直接每个日期对应的周几的名字。

DataFrame数据中的字符串列支持str接口,该接口提供了center、contains、count、endswith、find、extract、lower、split等大量属性和方法。

import numpy as np
import pandas as pd
import copy
#设置输出结果对齐方式
pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df = pd.read_excel(r'超市营业额2.xlsx',usecols=['日期','交易额'])


#深复制,不影响原来的df
dff = copy.deepcopy(df)
# 把日期列替换为周几
dff['日期'] = pd.to_datetime(df['日期']).dt.weekday
#按周几分组,查看交易额平均值,四舍五入
print('按周几分组查看交易额平均值')
dff = dff.groupby('日期').mean().apply(round)
dff.index.name = '周几'
print(dff)
按周几分组查看交易额平均值
      交易额
周几        
0     1233.0
1     1258.0
2     1224.0
3     1830.0
4     1277.0
5     1306.0
6     1254.0
dff=copy.deepcopy(df) 
#修改日期列,只保留年份和月份 
dff['日期']=dff['日期'].str.extract(r'(\d{4}-\d{2})') 
print('只查看年份和月份')
print(dff[:5])
只查看年份和月份
      日期  交易额
0  2019-03  1664.0
1  2019-03   954.0
2  2019-03  1407.0
3  2019-03  1320.0
4  2019-03   994.0
#按字符串形式的日期最后一位数进行分组 
#该月1、11、21、31日汇总为一组,2、12、22日为一组,以此类推 
print('按日期的日进行分组查看交易额平均值') 
print(df.groupby(df['日期'].str.__getitem__(-1)).mean().apply(round)) 
按日期的日进行分组查看交易额平均值
      交易额
日期        
0     1178.0
1     1264.0
2     1273.0
3     1317.0
4     1801.0
5     1223.0
6     1292.0
7     1216.0
8     1508.0
9     1266.0
#查看日期尾数为6的数据前12行 
print('査着日期尾数力 6 的数据')
print(df[df['日期'].str.endswith('6')][:12])

査着日期尾数力 6 的数据
           日期  交易额
40   2019-03-06  1037.0
41   2019-03-06   822.0
42   2019-03-06  1200.0
43   2019-03-06  1245.0
44   2019-03-06  1699.0
45   2019-03-06  1199.0
46   2019-03-06  1162.0
47   2019-03-06  1778.0
121  2019-03-16  1788.0
122  2019-03-16  1590.0
123  2019-03-16  1498.0
124  2019-03-16     NaN
#查看日期尾数为12的数据 #slice()方法接收3个参数,分别为起始位置、结束位置和步长 
print('日期尾数为12的交易数据') 
print(df[df.日期.str.slice(-2)=='12'])
日期尾数为12的交易数据
          日期  交易额
88  2019-03-12  1183.0
89  2019-03-12   979.0
90  2019-03-12  1651.0
91  2019-03-12  1435.0
92  2019-03-12  1302.0
93  2019-03-12  1317.0
94  2019-03-12   831.0
95  2019-03-12  1530.0
#日期中月份或天数包含2的交易数据第15到第25行 
print('日期中月份或天数包含2的交易数据') 
print(df[df.日期.str.slice(-5).str.contains('2')][15:25])
日期中月份或天数包含2的交易数据
           日期  交易额
95   2019-03-12  1530.0
153  2019-03-20  1332.0
154  2019-03-20  1485.0
155  2019-03-20   980.0
156  2019-03-20  1615.0
157  2019-03-20  1037.0
158  2019-03-20  1649.0
159  2019-03-20  1046.0
160  2019-03-20   829.0
161  2019-03-21  1528.0

7.2.16 查看DataFrame的内存占用情况

import pandas as pd

# 读取全部数据,使用默认索引
df = pd.read_excel(r'超市营业额2.xlsx')

print('交易额列占用内存情况'.ljust(20,'='))
print(df['交易额'].memory_usage())

print('内存占用情况'.ljust(20,'='))
print(df.memory_usage())

print('内存占用总额'.ljust(20,'='))
print(df.memory_usage().sum())

print('使用df.info()查看内存占用'.ljust(20,'='))
df.info()

交易额列占用内存情况==========
2120
内存占用情况==============
Index      128
工号      1992
姓名      1992
日期      1992
时段      1992
交易额    1992
柜台      1992
dtype: int64
内存占用总额==============
12080
使用df.info()查看内存占用===
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 249 entries, 0 to 248
Data columns (total 6 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   工号      249 non-null    int64  
 1   姓名      249 non-null    object 
 2   日期      249 non-null    object 
 3   时段      249 non-null    object 
 4   交易额     246 non-null    float64
 5   柜台      249 non-null    object 
dtypes: float64(1), int64(1), object(4)
memory usage: 11.8+ KB

7.2.17 数据拆分与合并

——concat()函数与append()方法

根据不同的需要,可以对DataFrame使用切片或loc等运算按行或列进行拆分,得到多个DataFrame结构。扩展库pandas提供了concat()函数用于合并多个DataFrame结构,完整语法如下:

concat(objs, axis=0, join=‘outer’, join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, copy=True)

参数objs表示包含多个Series、DataFrame或Panel对象的序列;

参数axis默认为0,表示按行进行纵向合并和扩展。

import numpy as np
import pandas as pd
import copy
#设置输出结果对齐方式
pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df = pd.read_excel(r'超市营业额2.xlsx')
df5 = pd.read_excel(r'超市营业额2.xlsx',sheet_name='Sheet2')
#按行拆分
df1 = df[:3]
df2 = df[50:53]
#按行进行合并,要求多个dataFarame结构相同
df3 = pd.concat([df1,df2,df5])
#使用append()方法按行合并,忽略原来的索引
df4 = df1.append([df2,df5],ignore_index=True)
#按列进行拆分
df6 = df.loc[:,['姓名','柜台','交易额']]

print(df1,df2,df3,df4,df[:5],sep='\n\n')
   工号  姓名        日期           时段  交易额    柜台
0  1001  张三  2019-03-01   9:00-14:00  1664.0  化妆品
1  1002  李四  2019-03-01  14:00-21:00   954.0  化妆品
2  1003  王五  2019-03-01   9:00-14:00  1407.0    食品

    工号  姓名        日期           时段  交易额    柜台
50  1004  赵六  2019-03-07   9:00-14:00  1340.0    食品
51  1004  赵六  2019-03-07  14:00-21:00   942.0    食品
52  1005  周七  2019-03-07   9:00-14:00  1465.0  日用品

    工号  姓名        日期           时段  交易额      柜台
0   1001  张三  2019-03-01   9:00-14:00  1664.0    化妆品
1   1002  李四  2019-03-01  14:00-21:00   954.0    化妆品
2   1003  王五  2019-03-01   9:00-14:00  1407.0      食品
50  1004  赵六  2019-03-07   9:00-14:00  1340.0      食品
51  1004  赵六  2019-03-07  14:00-21:00   942.0      食品
52  1005  周七  2019-03-07   9:00-14:00  1465.0    日用品
0   1001  张三  2019-04-01   9:00-14:00  1367.0    化妆品
1   1002  李四  2019-04-01  14:00-21:00  1005.0    化妆品
2   1003  王五  2019-04-01   9:00-14:00  1460.0      食品
3   1004  赵六  2019-04-01  14:00-21:00  1270.0      食品
4   1005  周七  2019-04-01   9:00-14:00  1123.0    日用品
5   1006  钱八  2019-04-01  14:00-21:00  1321.0    日用品
6   1007  孙九  2019-04-01   9:00-14:00  1364.0  蔬菜水果
7   1007  孙九  2019-04-01  14:00-21:00  1633.0  蔬菜水果

    工号  姓名        日期           时段  交易额      柜台
0   1001  张三  2019-03-01   9:00-14:00  1664.0    化妆品
1   1002  李四  2019-03-01  14:00-21:00   954.0    化妆品
2   1003  王五  2019-03-01   9:00-14:00  1407.0      食品
3   1004  赵六  2019-03-07   9:00-14:00  1340.0      食品
4   1004  赵六  2019-03-07  14:00-21:00   942.0      食品
5   1005  周七  2019-03-07   9:00-14:00  1465.0    日用品
6   1001  张三  2019-04-01   9:00-14:00  1367.0    化妆品
7   1002  李四  2019-04-01  14:00-21:00  1005.0    化妆品
8   1003  王五  2019-04-01   9:00-14:00  1460.0      食品
9   1004  赵六  2019-04-01  14:00-21:00  1270.0      食品
10  1005  周七  2019-04-01   9:00-14:00  1123.0    日用品
11  1006  钱八  2019-04-01  14:00-21:00  1321.0    日用品
12  1007  孙九  2019-04-01   9:00-14:00  1364.0  蔬菜水果
13  1007  孙九  2019-04-01  14:00-21:00  1633.0  蔬菜水果

   工号  姓名        日期           时段  交易额    柜台
0  1001  张三  2019-03-01   9:00-14:00  1664.0  化妆品
1  1002  李四  2019-03-01  14:00-21:00   954.0  化妆品
2  1003  王五  2019-03-01   9:00-14:00  1407.0    食品
3  1004  赵六  2019-03-01  14:00-21:00  1320.0    食品
4  1005  周七  2019-03-01   9:00-14:00   994.0  日用品

——merge()方法

merge(right, how=‘inner’, on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=(‘_x’, ‘_y’), copy=True, indicator=False)

参数right表示另一个DataFrame结构;

The value of the parameter how can be one of 'left', 'right', 'outer' or 'inner', indicating the way of data connection;

The parameter on is used to specify the column name or a list containing several column names when connecting. It is required that the specified column name exists in both DataFrames. If there is no parameter to specify the connection key, it will be connected according to the intersection of the column names of the two DataFrames. ;

The parameters left_on and right_on are used to specify the left column name label and the right column name label respectively when connecting.

import numpy as np
import pandas as pd
import copy
#设置输出结果对齐方式
pd.set_option('display.unicode.ambiguous_as_wide',True)
pd.set_option('display.unicode.east_asian_width',True)

df1 = pd.read_excel(r'超市营业额2.xlsx')
df2 = pd.read_excel(r'超市营业额2.xlsx',sheet_name='Sheet3')
#按同名的列合并,随机查看10行数据 
rows=np.random.randint(0,len(df1),10)
print(pd.merge(df1,df2).iloc[rows,:],end='\n\n') 
#按工号合并,指定其他同名列的后级 
print(pd.merge(df1,df2,on='工号', suffixes=['_x','_y']).iloc[rows,:],end='\n\n')

     工号  姓名        日期           时段  交易额      柜台  职级
83   1002  李四  2019-03-31   9:00-14:00  1274.0    化妆品  主管
217  1006  钱八  2019-03-05  14:00-21:00  1578.0    日用品  员工
156  1004  赵六  2019-03-22  14:00-21:00   981.0    日用品  员工
171  1005  周七  2019-03-02   9:00-14:00  1444.0    日用品  员工
178  1005  周七  2019-03-06  14:00-21:00  1778.0  蔬菜水果  员工
187  1005  周七  2019-03-12  14:00-21:00  1317.0    化妆品  员工
199  1005  周七  2019-03-20   9:00-14:00  1046.0      食品  员工
52   1002  李四  2019-03-10   9:00-14:00  1478.0  蔬菜水果  主管
55   1002  李四  2019-03-13  14:00-21:00    98.0    日用品  主管
108  1003  王五  2019-03-19  14:00-21:00  1026.0    化妆品  组长

     工号 姓名_x        日期           时段  交易额      柜台 姓名_y  职级
83   1002   李四  2019-03-31   9:00-14:00  1274.0    化妆品   李四  主管
217  1006   钱八  2019-03-05  14:00-21:00  1578.0    日用品   钱八  员工
156  1004   赵六  2019-03-22  14:00-21:00   981.0    日用品   赵六  员工
171  1005   周七  2019-03-02   9:00-14:00  1444.0    日用品   周七  员工
178  1005   周七  2019-03-06  14:00-21:00  1778.0  蔬菜水果   周七  员工
187  1005   周七  2019-03-12  14:00-21:00  1317.0    化妆品   周七  员工
199  1005   周七  2019-03-20   9:00-14:00  1046.0      食品   周七  员工
52   1002   李四  2019-03-10   9:00-14:00  1478.0  蔬菜水果   李四  主管
55   1002   李四  2019-03-13  14:00-21:00    98.0    日用品   李四  主管
108  1003   王五  2019-03-19  14:00-21:00  1026.0    化妆品   王五  组长

——join() method

The join() method of the DataFrame structure can also realize the merging of the left table (DataFrame calling the join() method) and the right table by column. If the other index of the right table is the same as the value of a column of the left table, it can be directly connected. To join the value of a column in the other table with the left table, you need to call the set_index() method on the right table other to set the column as an index.

join(other, on=None, how=‘left’, lsuffix=‘’, rsuffix=‘’, sort=False)

The parameter other represents another DataFrame structure, which is the right table;

The parameter on is used to specify the column name of the left table based on the connection, if not specified, the connection will be performed according to the value of the left table index index;

The meaning of the parameter how is the same as that of the merge() method;

The parameters lsuffix and rsuffix are used to specify the suffix of the column name.

#两个表都设置工号列为索引 
print(df1.set_index('工号').join(df2.set_index('工号'), lsuffix='_x' ,rsuffix='_y').iloc[rows,:])
     姓名_x        日期           时段  交易额      柜台 姓名_y  职级
工号                                                                 
1002   李四  2019-03-31   9:00-14:00  1274.0    化妆品   李四  主管
1006   钱八  2019-03-05  14:00-21:00  1578.0    日用品   钱八  员工
1004   赵六  2019-03-22  14:00-21:00   981.0    日用品   赵六  员工
1005   周七  2019-03-02   9:00-14:00  1444.0    日用品   周七  员工
1005   周七  2019-03-06  14:00-21:00  1778.0  蔬菜水果   周七  员工
1005   周七  2019-03-12  14:00-21:00  1317.0    化妆品   周七  员工
1005   周七  2019-03-20   9:00-14:00  1046.0      食品   周七  员工
1002   李四  2019-03-10   9:00-14:00  1478.0  蔬菜水果   李四  主管
1002   李四  2019-03-13  14:00-21:00    98.0    日用品   李四  主管
1003   王五  2019-03-19  14:00-21:00  1026.0    化妆品   王五  组长

Guess you like

Origin blog.csdn.net/J__aries/article/details/130856010