Python Pandas基础使用

发布于:2024-06-29 ⋅ 阅读:(11) ⋅ 点赞:(0)

Python Pandas基础使用

记录一下Python Pandas使用,将网上的文章汇总于此篇文章,用于后续查缺补漏(文章内容主要来源于:极客教程)。

Pandas 可以从各种文件格式比如 CSV、JSON、SQL、Microsoft Excel 导入数据。

Pandas 可以对各种数据进行运算操作,比如归并、再成形、选择,还有数据清洗和数据加工特征。

Pandas 广泛应用在学术、金融、统计学等各个数据分析领域。

数据类型

Pandas 的主要数据结构是 Series (一维数据)与 DataFrame(二维数据)。

  • Series 是一种类似于一维数组的对象,它由一组数据(各种 Numpy 数据类型)以及一组与之相关的数据标签(即索引)组成。
  • DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共同用一个索引)。

维度与描述:

最好的理解这些数据结构的方式是将高维数据结构看作是低维数据结构的容器。例如,DataFrame是Series的容器,Panel是DataFrame的容器。

数据结构 维度 描述
Series 1 一维带标签的同质数组,大小不可变。
Data Frames 2 通用的二维带标签,大小可变的表格结构,其中列的类型可能不同。
Panel 3 通用的三维带标签,大小可变的数组。

构建和处理二维或多维数组是一项繁琐的任务,用户在编写函数时需要考虑数据集的方向,但使用Pandas数据结构可以减少用户的心力。

例如,对于表格数据(DataFrame),更有语义意义的是考虑行(索引)和列,而不是轴0和轴1。

可变性:

所有Pandas数据结构都是可变的(可以更改),除了Series之外,所有其他结构的大小都是可变的。Series的大小是不可变的。

注意 - DataFrame被广泛使用,是最重要的数据结构之一。Panel的使用较少。

Series

Series是一个一维数组-like的结构,具有同质数据。例如,以下系列是一组整数10、23、56,…

10 23 56 17 52 61 73 90 26 72

关键要点:

  • 同质数据
  • 尺寸不可变
  • 数据值可变

DataFrame

DataFrame是一个二维数组,包含异质数据。例如,

Name Age Gender Rating
Steve 32 Male 3.45
Lia 28 Female 4.6
Vin 45 Male 3.9
Katie 38 Female 2.78

该表格代表了一个组织中销售团队的数据以及他们的整体绩效评级。数据以行和列的方式呈现,每列代表一个属性,每行代表一个人。

列的数据类型

四列的数据类型如下:

Column Type
Name String
Age Integer
Gender String
Rating Float

关键点:

  • 异构数据
  • 大小可变
  • 数据可变

Panel

Panel是一个具有异构数据的三维数据结构。用图形表示面板是困难的。但可以将面板看作是DataFrame的容器。

关键点:

  • 异构数据
  • 大小可变
  • 数据可变

创建

Series

可以使用以下构造函数创建pandas Series-

pandas.Series( data, index, dtype, copy)

构造函数的参数如下:

序号 参数和描述
1 data 数据可以是ndarray、列表、常量等形式
2 index 索引值必须唯一且可哈希,长度与数据相同。如果没有传递索引,则默认为 np.arrange(n)
3 dtype 数据类型。如果为None,则会推断数据类型
4 copy 复制数据。默认为False

一系列可以使用各种输入来创建,如−

  • 数组
  • 字典
  • 标量值或常数

常见的几种创建方法:

  1. 创建一个空系列
  2. 从ndarray创建Series
  3. 从字典创建一个系列
  4. 从标量创建 Series
import pandas as pd
import numpy as np


# 1. 创建一个空系列
s = pd.Series()
print s
# 输出如下
Series([], dtype: float64)


# 2. 从ndarray创建Series
data = np.array(['a','b','c','d'])
s = pd.Series(data)
print s

0   a
1   b
2   c
3   d
dtype: object

data = np.array(['a','b','c','d'])
s = pd.Series(data,index=[100,101,102,103])
print s

100  a
101  b
102  c
103  d
dtype: object


# 3. 从字典创建一个系列
data = {'a' : 0., 'b' : 1., 'c' : 2.}
s = pd.Series(data)
print s

a 0.0
b 1.0
c 2.0
dtype: float64

data = {'a' : 0., 'b' : 1., 'c' : 2.}
s = pd.Series(data,index=['b','c','d','a'])
print s

b 1.0
c 2.0
d NaN
a 0.0
dtype: float64


# 4. 从标量创建 Series
s = pd.Series(5, index=[0, 1, 2, 3])
print s

0  5
1  5
2  5
3  5
dtype: int64

常见的几种使用方法:

  1. 从Series中按位置访问数据
  2. 使用标签(索引)检索数据
import pandas as pd
import numpy as np

# 1. 从Series中按位置访问数据
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])
#retrieve the first element
print s[0]

1

#retrieve the first three element
print s[:3]

a  1
b  2
c  3
dtype: int64

#retrieve the last three element
print s[-3:]

c  3
d  4
e  5
dtype: int64

# 2. 使用标签(索引)检索数据
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])
#retrieve a single element
print s['a']

1

#retrieve multiple elements
print s[['a','c','d']]

a  1
c  3
d  4
dtype: int64

#retrieve multiple elements
print s['f']

…
KeyError: 'f'

DataFrame

可以使用以下构造器创建pandas DataFrame:

pandas.DataFrame( data, index, columns, dtype, copy)

构造函数的参数如下所示:

序号 参数和描述
1 数据(data) 数据可以是各种形式,如ndarray、series、map、lists、dict、constants和另一个DataFrame。
2 索引(index) 用于行标签的索引,如果没有传递索引,则默认为np.arange(n)。
3 列标签(columns) 用于列标签的可选默认语法是np.arange(n),仅当没有传递索引时才成立。
4 数据类型(dtype) 每列的数据类型。
5 复制(copy) 如果默认值为False,则用于复制数据的命令(或其他命令)。

常见的几种创建方法:

  1. 创建一个空的DataFrame
  2. 从列表创建DataFrame
  3. 从字典的ndarrays /列表创建DataFrame
  4. 从字典列表创建DataFrame
  5. 从Series字典创建DataFrame
import pandas as pd

# 1. 创建一个空的DataFrame
df = pd.DataFrame()
print df

Empty DataFrame
Columns: []
Index: []


# 2. 从列表创建DataFrame
data = [1,2,3,4,5]
df = pd.DataFrame(data)
print df

0
0    1
1    2
2    3
3    4
4    5

data = [['Alex',10],['Bob',12],['Clarke',13]]
df = pd.DataFrame(data,columns=['Name','Age'])
print df

Name      Age
0     Alex      10
1     Bob       12
2     Clarke    13

data = [['Alex',10],['Bob',12],['Clarke',13]]
df = pd.DataFrame(data,columns=['Name','Age'],dtype=float)
print df

Name     Age
0     Alex     10.0
1     Bob      12.0
2     Clarke   13.0


# 3. 从字典的ndarrays /列表创建DataFrame
data = {'Name':['Tom', 'Jack', 'Steve', 'Ricky'],'Age':[28,34,29,42]}
df = pd.DataFrame(data)
print df

Age      Name
0     28        Tom
1     34       Jack
2     29      Steve
3     42      Ricky

data = {'Name':['Tom', 'Jack', 'Steve', 'Ricky'],'Age':[28,34,29,42]}
df = pd.DataFrame(data, index=['rank1','rank2','rank3','rank4'])
print df

Age    Name
rank1    28      Tom
rank2    34     Jack
rank3    29    Steve
rank4    42    Ricky


# 4. 从字典列表创建DataFrame
data = [{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}]
df = pd.DataFrame(data)
print df

a    b      c
0   1   2     NaN
1   5   10   20.0

data = [{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}]
df = pd.DataFrame(data, index=['first', 'second'])
print df

a   b       c
first   1   2     NaN
second  5   10   20.0

data = [{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}]
#With two column indices, values same as dictionary keys
df1 = pd.DataFrame(data, index=['first', 'second'], columns=['a', 'b'])
#With two column indices with one index with other name
df2 = pd.DataFrame(data, index=['first', 'second'], columns=['a', 'b1'])
print df1
print df2

#df1 output
         a  b
first    1  2
second   5  10
#df2 output
         a  b1
first    1  NaN
second   5  NaN


# 5. 从Series字典创建DataFrame
d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print df

one    two
a     1.0    1
b     2.0    2
c     3.0    3
d     NaN    4


常见的几种使用方法:

  1. 列选择
  2. 列相加
  3. 列删除
  4. 按标签选择
  5. 根据整数位置进行选择
  6. 选择行
  7. 添加行
  8. 删除行
import pandas as pd

# 1. 列选择
d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print df ['one']

a     1.0
b     2.0
c     3.0
d     NaN
Name: one, dtype: float64


# 2. 列相加
d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
# Adding a new column to an existing DataFrame object with column label by passing new series
print ("Adding a new column by passing as Series:")
df['three']=pd.Series([10,20,30],index=['a','b','c'])
print df

print ("Adding a new column using the existing columns in DataFrame:")
df['four']=df['one']+df['three']
print df

Adding a new column by passing as Series:
     one   two   three
a    1.0    1    10.0
b    2.0    2    20.0
c    3.0    3    30.0
d    NaN    4    NaN

Adding a new column using the existing columns in DataFrame:
      one   two   three    four
a     1.0    1    10.0     11.0
b     2.0    2    20.0     22.0
c     3.0    3    30.0     33.0
d     NaN    4     NaN     NaN


# 3. 列删除
d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']), 
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd']), 
   'three' : pd.Series([10,20,30], index=['a','b','c'])}
df = pd.DataFrame(d)
print ("Our dataframe is:")
print df

# using del function
print ("Deleting the first column using DEL function:")
del df['one']
print df

# using pop function
print ("Deleting another column using POP function:")
df.pop('two')
print df

Our dataframe is:
      one   three  two
a     1.0    10.0   1
b     2.0    20.0   2
c     3.0    30.0   3
d     NaN     NaN   4

Deleting the first column using DEL function:
      three    two
a     10.0     1
b     20.0     2
c     30.0     3
d     NaN      4

Deleting another column using POP function:
   three
a  10.0
b  20.0
c  30.0
d  NaN


# 4. 按标签选择
d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']), 
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print df.loc['b']

one 2.0
two 2.0
Name: b, dtype: float64


# 5. 根据整数位置进行选择
d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print df.iloc[2]

one   3.0
two   3.0
Name: c, dtype: float64


# 6. 选择行
d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']), 
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print df[2:4]

one  two
c  3.0    3
d  NaN    4


# 7. 添加行
df = pd.DataFrame([[1, 2], [3, 4]], columns = ['a','b'])
df2 = pd.DataFrame([[5, 6], [7, 8]], columns = ['a','b'])
df = df.append(df2)
print df

a  b
0  1  2
1  3  4
0  5  6
1  7  8


# 8. 删除行
df = pd.DataFrame([[1, 2], [3, 4]], columns = ['a','b'])
df2 = pd.DataFrame([[5, 6], [7, 8]], columns = ['a','b'])
df = df.append(df2)
# Drop rows with label 0
df = df.drop(0)
print df

a b
1 3 4
1 7 8


CSV读/写:

import pandas as pd

# 读取 csv文件
df = pd.read_csv('nba.csv')

# 保存 dataframe
df.to_csv('site.csv')

JSON读/写:

nested_list.json 文件内容:

{
    "school_name": "ABC primary school",
    "class": "Year 1",
    "students": [
    {
        "id": "A001",
        "name": "Tom",
        "math": 60,
        "physics": 66,
        "chemistry": 61
    },
    {
        "id": "A002",
        "name": "James",
        "math": 89,
        "physics": 76,
        "chemistry": 51
    },
    {
        "id": "A003",
        "name": "Jenny",
        "math": 79,
        "physics": 90,
        "chemistry": 78
    }]
}
import pandas as pd
import json


# JSON读取,方式一:
df = pd.read_json('sites.json')

# 方式二:
# 使用 Python JSON 模块载入数据
with open('nested_list.json','r') as f:
    data = json.loads(f.read())

# 展平数据(复杂的JSON结构可以使用.json_normalize方法)
df_nested_list = pd.json_normalize(data, record_path =['students'])
print(df_nested_list)

基本使用

Series的基本功能:

Sr.No. 属性或方法 & 说明
1 axes 返回行轴标签的列表
2 dtype 返回对象的dtype。
3 empty 返回True,如果_series——是空的。
4 ndim 返回基础数据的维数的数量,按定义1。
5 size 返回基础数据中元素的数量。
6 values 返回级数作为ndarray。
7 head() 返回前n行。
8 tail() 返回最后n行。

DataFrame的基本功能:

编号 属性或方法 & 描述
1 T 将行和列进行转置。
2 axes 返回一个列表,其中包含行轴标签和列轴标签作为唯一成员。
3 dtypes 返回此对象中的数据类型。
4 empty 如果NDFrame完全为空[没有任何项目],则为True;如果任何轴的长度为0,则为True。
5 ndim 轴/数组维度的数量。
6 shape 返回一个表示DataFrame维度的元组。
7 size NDFrame中元素的数量。
8 values NDFrame的Numpy表示。
9 head() 返回前n行。
10 tail() 返回最后n行。

描述性统计

让我们现在了解Python Pandas中描述性统计的函数。以下表格列出了重要的函数:

序号 函数 描述
1 count() 非空值的观察数量
2 sum() 值的总和
3 mean() 值的平均值
4 median() 值的中位数
5 mode() 值的众数
6 std() 值的标准差
7 min() 最小值
8 max() 最大值
9 abs() 绝对值
10 prod() 值的乘积
11 cumsum() 累计求和
12 cumprod() 累计乘积

注意 - 由于DataFrame是一种异构数据结构,通用操作不适用于所有函数。

  • 像**sum(),cumsum()**这样的函数,对于数字和字符(或字符串)数据元素都可以正常工作而不会出错。虽然通常情况下很少使用字符聚合,但这些函数不会引发任何异常。
  • abs(),cumprod() 这样的函数,在DataFrame包含字符或字符串数据时会抛出异常,因为不能执行此类操作

汇总数据:

describe() 函数计算有关DataFrame列的统计摘要。

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack',
   'Lee','David','Gasper','Betina','Andres']),
   'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])
}

#Create a DataFrame
df = pd.DataFrame(d)
print df.describe()

它的 输出 如下−

Age         Rating
count    12.000000      12.000000
mean     31.833333       3.743333
std       9.232682       0.661628
min      23.000000       2.560000
25%      25.000000       3.230000
50%      29.500000       3.790000
75%      35.500000       4.132500
max      51.000000       4.800000

该函数提供了 平均值、标准差IQR值 。函数排除字符列,并给出数值列的摘要信息。 ‘include’ 是用于传递需要考虑进行摘要的列的必要信息的参数。接受值的列表,默认为’number’。

  • object - 总结字符串列
  • number - 总结数值列
  • all - 总结所有列在一起(不应将其作为列表值传递)

现在,在程序中使用以下语句并检查输出 –

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack',
   'Lee','David','Gasper','Betina','Andres']),
   'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])
}

#Create a DataFrame
df = pd.DataFrame(d)
print df.describe(include=['object'])

它的 输出 如下−

Name
count       12
unique      12
top      Ricky
freq         1

现在,使用以下语句并检查输出−

import pandas as pd
import numpy as np

#Create a Dictionary of series
d = {'Name':pd.Series(['Tom','James','Ricky','Vin','Steve','Smith','Jack',
   'Lee','David','Gasper','Betina','Andres']),
   'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])
}

#Create a DataFrame
df = pd.DataFrame(d)
print df. describe(include='all')

它的输出如下:

Age          Name       Rating
count   12.000000        12    12.000000
unique        NaN        12          NaN
top           NaN     Ricky          NaN
freq          NaN         1          NaN
mean    31.833333       NaN     3.743333
std      9.232682       NaN     0.661628
min     23.000000       NaN     2.560000
25%     25.000000       NaN     3.230000
50%     29.500000       NaN     3.790000
75%     35.500000       NaN     4.132500
max     51.000000       NaN     4.800000

重新索引

重新索引 可以更改DataFrame的行标签和列标签。重新索引意味着将数据调整为与给定的一组标签相匹配。

索引可以通过多种操作来实现,例如:

  • 重新排序现有数据以匹配新的标签集。
  • 在标签位置上插入缺失值(NA),以对应没有该标签的数据。

示例:

import pandas as pd
import numpy as np

N=20

df = pd.DataFrame({
   'A': pd.date_range(start='2016-01-01',periods=N,freq='D'),
   'x': np.linspace(0,stop=N-1,num=N),
   'y': np.random.rand(N),
   'C': np.random.choice(['Low','Medium','High'],N).tolist(),
   'D': np.random.normal(100, 10, size=(N)).tolist()
})

#reindex the DataFrame
df_reindexed = df.reindex(index=[0,2,5], columns=['A', 'C', 'B'])

print df_reindexed

它的 输出 如下:

A    C     B
0  2016-01-01  Low   NaN
2  2016-01-03  High  NaN
5  2016-01-06  Low   NaN
  1. 重新索引以与其他对象对齐

您可能希望将一个对象的轴重新索引,使其标签与另一个对象相同。请考虑以下示例以更好地理解。

示例:

import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.random.randn(10,3),columns=['col1','col2','col3'])
df2 = pd.DataFrame(np.random.randn(7,3),columns=['col1','col2','col3'])

df1 = df1.reindex_like(df2)
print df1

它的输出如下所示:

col1         col2         col3
0    -2.467652    -1.211687    -0.391761
1    -0.287396     0.522350     0.562512
2    -0.255409    -0.483250     1.866258
3    -1.150467    -0.646493    -0.222462
4     0.152768    -2.056643     1.877233
5    -1.155997     1.528719    -1.343719
6    -1.015606    -1.245936    -0.295275

注意 - 这里,DataFrame df1 被修改并像 df2 一样重新索引。列名应匹配,否则会为整个列标签添加 NAN。

  1. 在重新索引时填充

reindex() 可以接受一个可选参数 method,它是一种填充方法,取值如下:

  • pad/ffill - 前向填充值
  • bfill/backfill - 后向填充值
  • nearest - 从最近的索引值填充

示例:

import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.random.randn(6,3),columns=['col1','col2','col3'])
df2 = pd.DataFrame(np.random.randn(2,3),columns=['col1','col2','col3'])

# Padding NAN's
print df2.reindex_like(df1)

# Now Fill the NAN's with preceding Values
print ("Data Frame with Forward Fill:")
print df2.reindex_like(df1,method='ffill')

它的 输出 如下所示−

col1        col2       col3
0    1.311620   -0.707176   0.599863
1   -0.423455   -0.700265   1.133371
2         NaN         NaN        NaN
3         NaN         NaN        NaN
4         NaN         NaN        NaN
5         NaN         NaN        NaN

Data Frame with Forward Fill:
         col1        col2        col3
0    1.311620   -0.707176    0.599863
1   -0.423455   -0.700265    1.133371
2   -0.423455   -0.700265    1.133371
3   -0.423455   -0.700265    1.133371
4   -0.423455   -0.700265    1.133371
5   -0.423455   -0.700265    1.133371

注意 - 最后四行是填充的。

  1. 重新索引时填充的限制

limit参数在重新索引时提供了更多的填充控制。limit指定连续匹配的最大计数。让我们通过以下示例来理解:

示例:

import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.random.randn(6,3),columns=['col1','col2','col3'])
df2 = pd.DataFrame(np.random.randn(2,3),columns=['col1','col2','col3'])

# Padding NAN's
print df2.reindex_like(df1)

# Now Fill the NAN's with preceding Values
print ("Data Frame with Forward Fill limiting to 1:")
print df2.reindex_like(df1,method='ffill',limit=1)

它的 输出 如下:

col1        col2        col3
0    0.247784    2.128727    0.702576
1   -0.055713   -0.021732   -0.174577
2         NaN         NaN         NaN
3         NaN         NaN         NaN
4         NaN         NaN         NaN
5         NaN         NaN         NaN

Data Frame with Forward Fill limiting to 1:
         col1        col2        col3
0    0.247784    2.128727    0.702576
1   -0.055713   -0.021732   -0.174577
2   -0.055713   -0.021732   -0.174577
3         NaN         NaN         NaN
4         NaN         NaN         NaN
5         NaN         NaN         NaN

注意 −注意,只有第7行由前面的第6行填充。然后,行保持不变。

  1. 重命名

rename()方法允许你基于某个映射(字典或Series)或任意函数来重新标记一个轴。

让我们考虑以下示例来了解这个。

import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.random.randn(6,3),columns=['col1','col2','col3'])
print df1

print ("After renaming the rows and columns:")
print df1.rename(columns={'col1' : 'c1', 'col2' : 'c2'},
index = {0 : 'apple', 1 : 'banana', 2 : 'durian'})

它的 输出 如下所示:

col1        col2        col3
0    0.486791    0.105759    1.540122
1   -0.990237    1.007885   -0.217896
2   -0.483855   -1.645027   -1.194113
3   -0.122316    0.566277   -0.366028
4   -0.231524   -0.721172   -0.112007
5    0.438810    0.000225    0.435479

After renaming the rows and columns:
                c1          c2        col3
apple     0.486791    0.105759    1.540122
banana   -0.990237    1.007885   -0.217896
durian   -0.483855   -1.645027   -1.194113
3        -0.122316    0.566277   -0.366028
4        -0.231524   -0.721172   -0.112007
5         0.438810    0.000225    0.435479

rename()方法提供了一个名为 inplace 的参数,默认为False,会复制底层数据。将 inplace=True 传递给该方法,可以原地重命名数据。

迭代

要遍历DataFrame的行,我们可以使用以下函数:

  • iteritems() - 遍历(键,值)对
  • iterrows() - 以(索引,系列)对的形式遍历行
  • itertuples() - 以namedtuples的形式遍历行

Example(迭代DataFrame每一行):

		concated_df = pd.DataFrame({
      'station_id_c':[1,2], 
      'win_s_max':[1.2, 2.3]
      # 此处省略其它...
    })

		# 转换为pojo
    for i, r in concated_df.iterrows():
        station_id_c = r['station_id_c']
        observe_time = r['observe_time']
        win_s_max = r['win_s_max']
        win_s_inst_max = r['win_s_inst_max']

        pojo = SurfStationHistoryDay()
        pojo.station_id_c = station_id_c
        pojo.observe_time = observe_time
        pojo.win_s_max = win_s_max
        pojo.win_s_inst_max = win_s_inst_max

        result_list.append(pojo)

排序

Pandas提供了两种排序方法。它们是−

  • 标签排序
  • 按数值排序

排序函数:

  • sort_index():按照索引排序
    • 通过将轴参数设为0或1,可以对列标签进行排序。默认情况下,axis=0,按行排序。
  • sort_values():按照数值排序
    • by=[‘column_name1’,‘column_name2’ ]
    • kind=‘mergesort’

处理文本数据

在本章中,我们将讨论基本Series/Index的字符串操作。在后续的章节中,我们将学习如何在DataFrame上应用这些字符串函数。

Pandas提供了一组字符串函数,使得对字符串数据的操作变得很容易。最重要的是,这些函数会忽略(或排除)缺失/NaN值。

几乎所有这些方法都适用于Python字符串函数(参考:https://docs.python.org/3/library/stdtypes.html#string-methods)。因此,将Series对象转换为字符串对象,然后执行操作。

现在让我们看看每个操作的执行情况。

序号 函数与描述
1 lower() 将Series/Index中的字符串转换为小写。
2 upper() 将Series/Index中的字符串转换为大写。
3 len() 计算字符串的长度。
4 strip() 帮助去除Series/Index中每个字符串两侧的空白(包括换行符)。
5 split(‘ ‘) 使用给定的模式拆分每个字符串。
6 cat(sep=’ ‘) 使用给定的分隔符连接Series/Index元素。
7 get_dummies() 返回具有One-Hot编码值的DataFrame。
8 contains(pattern) 对于每个元素,如果子字符串包含在元素中,则返回布尔值True,否则返回False。
9 replace(a,b) 替换值 a 为值 b
10 repeat(value) 重复每个元素指定次数。
11 count(pattern) 返回每个元素中模式出现的次数。
12 startswith(pattern) 如果Series/Index中的元素以模式开头,则返回True。
13 endswith(pattern) 如果Series/Index中的元素以pattern结尾,则返回true。
14 find(pattern) 返回pattern第一次出现的位置。
15 findall(pattern) 返回pattern所有出现的位置的列表。
16 swapcase 交换大小写。
17 islower() 检查Series/Index中每个字符串中的所有字符是否都为小写。返回布尔值。
18 isupper() 检查Series/Index中每个字符串中的所有字符是否都为大写。返回布尔值。
19 isnumeric() 检查Series/Index中每个字符串的所有字符是否都是数字。返回布尔值。

让我们现在创建一个Series并看看上面的所有函数是如何工作的。

让我们现在创建一个Series并看看上面的所有函数是如何工作的。

import pandas as pd
import numpy as np

s = pd.Series(['Tom', 'William Rick', 'John', 'Alber@t', np.nan, '1234','SteveSmith'])

print s

它的 输出 如下:

0            Tom
1   William Rick
2           John
3        Alber@t
4            NaN
5           1234
6    Steve Smith
dtype: object

lower():

import pandas as pd
import numpy as np

s = pd.Series(['Tom', 'William Rick', 'John', 'Alber@t', np.nan, '1234','SteveSmith'])

print s.str.lower()

这是它的 输出 结果-

0            tom
1   william rick
2           john
3        alber@t
4            NaN
5           1234
6    steve smith
dtype: object

其它函数省略…

选项和定制

Pandas提供了API来定制其行为的一些方面,其中显示功能被广泛使用。

该API由五个相关函数组成。它们是:

  • get_option()
  • set_option()
  • reset_option()
  • describe_option()
  • option_context()

让我们现在了解这些函数如何操作。

常用参数:

Sr.No 参数和描述
1 display.max_rows 显示要显示的最大行数
2 display.max_columns 显示要显示的最大列数
3 display.expand_frame_repr 显示要拉伸页面的DataFrame
4 display.max_colwidth 显示最大列宽
5 display.precision 显示十进制数的精度
  1. get_option(param)

get_option接受一个参数并将其值返回为下面的输出所示:

显示默认值。解释器读取此值并将行显示为此值作为显示上限。

import pandas as pd
print pd.get_option("display.max_rows")

它的 输出 如下:

60

显示默认的数据值数量。 解释器读取此值,并将以此值作为显示的上限来显示行。

import pandas as pd
print pd.get_option("display.max_columns")

它的输出如下:

20

这里,60和20是默认的配置参数值。

  1. set_option(param,value)

set_option接受两个参数,并将参数的值设置如下:

使用 set_option() ,我们可以更改默认显示的行数。

import pandas as pd

pd.set_option("display.max_rows",80)

print pd.get_option("display.max_rows")

它的输出如下所示−

80

使用 set_option() ,我们可以更改默认显示的行数。

import pandas as pd

pd.set_option("display.max_columns",30)

print pd.get_option("display.max_columns")

它的 输出 如下:

30
  1. reset_option()

重置选项 接受一个参数,并将值设置为默认值。

使用reset_option(),我们可以将值更改回默认的显示行数。

import pandas as pd

pd.reset_option("display.max_rows")
print pd.get_option("display.max_rows")

它的 输出 如下:

60
  1. describe_option(param)

describe_option 打印参数的描述。

使用reset_option(),我们可以将该值更改回默认要显示的行数。

import pandas as pd
pd.describe_option("display.max_rows")

它的 输出 如下-

display.max_rows : int
   If max_rows is exceeded, switch to truncate view. Depending on
   'large_repr', objects are either centrally truncated or printed as
   a summary view. 'None' value means unlimited.

   In case python/IPython is running in a terminal and `large_repr`
   equals 'truncate' this can be set to 0 and pandas will auto-detect
   the height of the terminal and print a truncated object which fits
   the screen height. The IPython notebook, IPython qtconsole, or
   IDLE do not run in a terminal and hence it is not possible to do
   correct auto-detection.
   [default: 60] [currently: 60]
  1. option_context()

option_context上下文管理器用于在 with语句 中临时设置选项。当退出 with块 时,选项值会自动恢复。

使用option_context(),我们可以临时设置值。

import pandas as pd
with pd.option_context("display.max_rows",10):
   print(pd.get_option("display.max_rows"))
   print(pd.get_option("display.max_rows"))

它的 输出 如下:

10
10

看一下第一个和第二个打印语句之间的区别。第一个语句打印的是由 option_context() 设置的值,在 with context 内部是临时的。在 with context 之后,第二个打印语句打印的是配置的值。

索引和选择数据

在这一章中,我们将讨论如何切片和切块日期以及通常获取pandas对象的子集。

Python和NumPy的索引操作符“[]”和属性操作符“.”快速而轻松地访问Pandas数据结构的各种用例。然而,由于要访问的数据类型事先未知,直接使用标准操作符在优化方面存在一些局限性。对于生产代码,我们建议您利用本章中介绍的优化的pandas数据访问方法。

Pandas现在支持三种类型的多轴索引;这三种类型在下表中列出 –

序号 索引和描述
1 .loc() 基于标签
2 .iloc() 基于整数
3 .ix() 标签和整数都能用
  1. .loc():Pandas提供了各种纯粹基于标签的索引方法。在切片时,起始边界也被包含在内。整数是有效的标签,但它们指的是标签,而不是位置。

.loc() 具有多个访问方法,如−

  • 单个标量标签
  • 标签列表
  • 切片对象
  • 布尔数组

loc 通过’,’分隔两个单个/列表/范围运算符。第一个表示行,第二个表示列。

# import the pandas library and aliasing as pd
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4),
index = ['a','b','c','d','e','f','g','h'], columns = ['A', 'B', 'C', 'D'])

# 1. 选取所有行,其中的A列
df.loc[:,'A']

# 2. 选取所有行,其中的A、C列
df.loc[:,['A','C']]

# 3. 选其中几行, 所有列
df.loc['a':'h']

# 4. 获取其中'a'行,判断是否大于0,返回一个bool数组
print df.loc['a']>0
  1. .iloc():Pandas提供了各种方法来实现纯整数索引。与Python和Numpy一样,这些方法都是从0开始的索引。

各种访问方法如下所示:

  • 整数
  • 整数列表
  • 一段数值范围
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])

# Integer slicing
print df.iloc[:4]
print df.iloc[1:5, 2:4]

其输出结果如下:

A          B           C           D
0   0.699435   0.256239   -1.270702   -0.645195
1  -0.685354   0.890791   -0.813012    0.631615
2  -0.783192  -0.531378    0.025070    0.230806
3   0.539042  -1.284314    0.826977   -0.026251

           C          D
1  -0.813012   0.631615
2   0.025070   0.230806
3   0.826977  -0.026251
4   1.423332   1.130568
  1. .ix()

除了纯标签和整数基础外,Pandas还提供了一种混合方法来使用.ix()操作符进行选择和子集化对象。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])

# Integer slicing
print df.ix[:4]

它的 输出 如下:

A          B           C           D
0   0.699435   0.256239   -1.270702   -0.645195
1  -0.685354   0.890791   -0.813012    0.631615
2  -0.783192  -0.531378    0.025070    0.230806
3   0.539042  -1.284314    0.826977   -0.026251
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])
# Index slicing
print df.ix[:,'A']

它的 输出 如下:

0   0.699435
1  -0.685354
2  -0.783192
3   0.539042
4  -1.044209
5  -1.415411
6   1.062095
7   0.994204
Name: A, dtype: float64

符号的使用:

使用多轴索引从Pandas对象中获取值使用以下符号表示:

对象 索引器 返回类型
Series(序列) s.loc[indexer] 标量值
DataFrame(数据帧) df.loc[row_index,col_index] Series对象
Panel(面板) p.loc[item_index,major_index, minor_index] p.loc[item_index,major_index, minor_index]

属性访问:

可以使用属性运算符’.’来选择列。

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(8, 4), columns = ['A', 'B', 'C', 'D'])

print df.A

这个输出为

0   -0.478893
1    0.391931
2    0.336825
3   -1.055102
4   -0.165218
5   -0.328641
6    0.567721
7   -0.759399
Name: A, dtype: float64

统计函数

统计方法有助于理解和分析数据的行为。现在我们将学习一些可以应用于Pandas对象上的统计函数。

  1. 百分比变化

Series、DataFrames和Panel都具有 pct_change() 函数。该函数将每个元素与其前面的元素进行比较,并计算出变化百分比。

import pandas as pd
import numpy as np
s = pd.Series([1,2,3,4,5,4])
print s.pct_change()

df = pd.DataFrame(np.random.randn(5, 2))
print df.pct_change()

它的 输出 如下:

0        NaN
1   1.000000
2   0.500000
3   0.333333
4   0.250000
5  -0.200000
dtype: float64

            0          1
0         NaN        NaN
1  -15.151902   0.174730
2  -0.746374   -1.449088
3  -3.582229   -3.165836
4   15.601150  -1.860434

默认情况下, pct_change() 操作是基于列进行的;如果要逐行应用相同的操作,则使用 axis=1() 参数。

  1. Covariance

协方差应用于系列数据。Series对象有一个cov方法,用于计算系列对象之间的协方差。NA将被自动排除。

import pandas as pd
import numpy as np
s1 = pd.Series(np.random.randn(10))
s2 = pd.Series(np.random.randn(10))
print s1.cov(s2)

它的 输出 如下:

-0.12978405324

当在DataFrame上应用协方差方法时,计算 cov 所有列之间的协方差。

import pandas as pd
import numpy as np
frame = pd.DataFrame(np.random.randn(10, 5), columns=['a', 'b', 'c', 'd', 'e'])
print frame['a'].cov(frame['b'])
print frame.cov()

它的 输出 如下:

-0.58312921152741437

           a           b           c           d            e
a   1.780628   -0.583129   -0.185575    0.003679    -0.136558
b  -0.583129    1.297011    0.136530   -0.523719     0.251064
c  -0.185575    0.136530    0.915227   -0.053881    -0.058926
d   0.003679   -0.523719   -0.053881    1.521426    -0.487694
e  -0.136558    0.251064   -0.058926   -0.487694     0.960761

注意 - 在第一条语句中,观察 a 列和 b 列之间的 cov ,返回的值与DataFrame中的cov相同。

  1. 相关性

相关性显示任意两个数值数组(序列)之间的线性关系。有多种方法可以计算相关性,如pearson(默认)、spearman和kendall。

import pandas as pd
import numpy as np
frame = pd.DataFrame(np.random.randn(10, 5), columns=['a', 'b', 'c', 'd', 'e'])

print frame['a'].corr(frame['b'])
print frame.corr()

它的 输出 如下:

-0.383712785514

           a          b          c          d           e
a   1.000000  -0.383713  -0.145368   0.002235   -0.104405
b  -0.383713   1.000000   0.125311  -0.372821    0.224908
c  -0.145368   0.125311   1.000000  -0.045661   -0.062840
d   0.002235  -0.372821  -0.045661   1.000000   -0.403380
e  -0.104405   0.224908  -0.062840  -0.403380    1.000000

如果DataFrame中存在非数字列,则会自动排除。

  1. 数据排名

数据排名为数组中的每个元素产生排名。在出现并列的情况下,分配平均排名。

import pandas as pd
import numpy as np

s = pd.Series(np.random.np.random.randn(5), index=list('abcde'))
s['d'] = s['b'] # so there's a tie
print s.rank()

它的 输出 如下所示−

a  1.0
b  3.5
c  2.0
d  3.5
e  5.0
dtype: float64

排名(Rank)参数可选地接受一个升序参数,默认值为true;当为false时,数据被反向排名,较大的值被分配较小的排名。

排名支持不同的决胜方法,使用method参数指定 –

  • 平均(average) - 组内并列的平均排名
  • 最小(min) - 组内最低的排名
  • 最大(max) - 组内最高的排名
  • 首位(first) - 按照数组中出现的顺序分配排名

窗口函数

对于处理数值数据,Pandas提供了几种变体,如滚动、扩展和指数移动权重,用于窗口统计。其中包括 求和、均值、中位数、方差、协方差、相关系数 等等。

现在我们将学习如何在DataFrame对象上应用每一种函数。

  1. .rolling() 函数

此函数可以应用于数据系列。指定 window=n 参数,并在其之上应用适当的统计函数。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])
print df.rolling(window=3).mean()

它的 输出 如下:

A           B           C           D
2000-01-01        NaN         NaN         NaN         NaN
2000-01-02        NaN         NaN         NaN         NaN
2000-01-03   0.434553   -0.667940   -1.051718   -0.826452
2000-01-04   0.628267   -0.047040   -0.287467   -0.161110
2000-01-05   0.398233    0.003517    0.099126   -0.405565
2000-01-06   0.641798    0.656184   -0.322728    0.428015
2000-01-07   0.188403    0.010913   -0.708645    0.160932
2000-01-08   0.188043   -0.253039   -0.818125   -0.108485
2000-01-09   0.682819   -0.606846   -0.178411   -0.404127
2000-01-10   0.688583    0.127786    0.513832   -1.067156

注意 − 由于窗口大小为3,因此前两个元素为null,从第三个元素开始,值将为前 n , n-1n-2 元素的平均值。因此,我们还可以应用上面提到的各种函数。

实际应用案例:

# 逐1小时降水数据滚动计算逐3小时降水
hour_df['PRE_3h'] = hour_df['PRE_1h'].rolling('3h').sum()

# 最大3小时降水值
pre_max_3h = hour_df['PRE_3h'].max() if hour_df['PRE_3h'].dropna().shape[0] > 0 else None
  1. .expanding()函数

此函数可以应用于一系列数据。指定 min_periods=n 参数并在其上应用适当的统计函数。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])
print df.expanding(min_periods=3).mean()

它的 输出 如下−

A           B           C           D
2000-01-01        NaN         NaN         NaN         NaN
2000-01-02        NaN         NaN         NaN         NaN
2000-01-03   0.434553   -0.667940   -1.051718   -0.826452
2000-01-04   0.743328   -0.198015   -0.852462   -0.262547
2000-01-05   0.614776   -0.205649   -0.583641   -0.303254
2000-01-06   0.538175   -0.005878   -0.687223   -0.199219
2000-01-07   0.505503   -0.108475   -0.790826   -0.081056
2000-01-08   0.454751   -0.223420   -0.671572   -0.230215
2000-01-09   0.586390   -0.206201   -0.517619   -0.267521
2000-01-10   0.560427   -0.037597   -0.399429   -0.376886
  1. ewm()函数

ewm 函数应用于一系列的数据。您可以通过指定com、span或 halflife 参数,并在其上应用适当的统计函数来赋予数据指数权重。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(10, 4),
   index = pd.date_range('1/1/2000', periods=10),
   columns = ['A', 'B', 'C', 'D'])
print df.ewm(com=0.5).mean()

它的 输出 如下所示:

A           B           C           D
2000-01-01   1.088512   -0.650942   -2.547450   -0.566858
2000-01-02   0.865131   -0.453626   -1.137961    0.058747
2000-01-03  -0.132245   -0.807671   -0.308308   -1.491002
2000-01-04   1.084036    0.555444   -0.272119    0.480111
2000-01-05   0.425682    0.025511    0.239162   -0.153290
2000-01-06   0.245094    0.671373   -0.725025    0.163310
2000-01-07   0.288030   -0.259337   -1.183515    0.473191
2000-01-08   0.162317   -0.771884   -0.285564   -0.692001
2000-01-09   1.147156   -0.302900    0.380851   -0.607976
2000-01-10   0.600216    0.885614    0.569808   -1.110113

窗口函数主要用于通过平滑曲线来图形化地找出数据中的趋势。如果每天的数据有很大的变化并且有很多数据点可用,那么取样并绘制图表就是一种方法,应用窗口计算并绘制结果图表是另一种方法。通过这些方法,我们可以平滑曲线或趋势。

聚合函数

  • rolling()

缺失数据

常用处理特殊数据方法:

  • isnull():返回bool数组
  • notnull():返回bool数组
  • fillna()
  • dropna()
  • replace()

GroupBy

任何 groupby 操作都涉及对原始对象的以下操作。它们是 –

  • 拆分 对象
  • 应用 函数
  • 合并 结果

在许多情况下,我们将数据拆分为不同的组,并对每个子集应用一些功能。在应用功能中,我们可以执行以下操作 –

  • 聚合 - 计算摘要统计量
  • 变换 - 执行一些组特定的操作
  • 筛选 - 根据某些条件丢弃数据

常用函数:

  • groupby():按参数分组
  • groupby('Team').groups:查看分组
  • for name,group in grouped::遍历分组,name为分组名,group为分组列表
  • grouped.agg([np.sum, np.mean, np.std]):分组后聚合操作
  • grouped.transform(lambda x: (x - x.mean()) / x.std()*10):对组或列进行转换会返回一个与正在分组的对象大小相同的对象
  • df.groupby('Team').filter(lambda x: len(x) >= 3):过滤根据定义的条件筛选数据并返回数据的子集

合并/连接

常用函数:

  • merge()
  • `concat()
  1. merge()

Pandas提供了一个单一的函数 merge ,作为DataFrame对象之间所有标准数据库连接操作的入口点。

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
left_index=False, right_index=False, sort=True)

在这里,我们使用了以下参数−

  • left − 一个DataFrame对象。
  • right − 另一个DataFrame对象。
  • on − 要连接的列(名称)。必须在左侧和右侧的DataFrame对象中找到。
  • left_on − 从左侧DataFrame中用作键的列。可以是列名称或与DataFrame长度相等的数组。
  • right_on − 从右侧DataFrame中用作键的列。可以是列名称或与DataFrame长度相等的数组。
  • left_index − 如果 True, 则使用左侧DataFrame的索引(行标签)作为其连接键。对于具有MultiIndex(分层)的DataFrame,级数的数量必须与右侧DataFrame的连接键数量匹配。
  • right_index − 对于右侧DataFrame,与 left_index 的用法相同。
  • how − 一个’left’、’right’、’outer’、’inner’之一。默认为inner。下面每种方法都有详细描述。
  • sort − 按字典顺序对连接键对应的结果DataFrame进行排序。默认为True,将其设置为False将在许多情况下大大提高性能。
  1. concat()
pd.concat(objs,axis=0,join='outer',join_axes=None,
ignore_index=False)
  • objs − 这是一系列或映射的Series、DataFrame或Panel对象。
  • axis − {0, 1, …},默认为0。这是要沿着连接的轴。
  • join − {‘inner’, ‘outer’},默认为‘outer’。如何处理其他轴上的索引。对于并集使用Outer,对于交集使用Inner。
  • ignore_index − 布尔型, 默认为False。如果为True,则不使用连接轴上的索引值。 结果轴将被标记为0,…,n-1。
  • join_axes − 这是索引对象的列表。特定的索引用于其他(n-1)轴,而不执行内部/外部集合逻辑。

日期功能

常用函数:

  • pd.date_range():通过指定周期和频率,我们可以创建日期序列。默认情况下,日期范围的频率是天。
  • pd.bdate_range():表示营业日期范围。与date_range()不同,它排除星期六和星期日。

示例:

import pandas as pd


print pd.date_range('1/1/2011', periods=5,freq='M')

DatetimeIndex(['2011-01-31', '2011-02-28', '2011-03-31', '2011-04-30', '2011-05-31'],
   dtype='datetime64[ns]', freq='M')


start = pd.datetime(2011, 1, 1)
end = pd.datetime(2011, 1, 5)
print pd.date_range(start, end)

DatetimeIndex(['2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'],
   dtype='datetime64[ns]', freq='D')

一些字符串别名被赋予了常见的时间序列频率。我们将这些别名称为偏移别名。

别名 描述 别名 描述
B 工作日频率 BQS 季度开始的工作日频率
D 日历日频率 A 年度结束频率
W 每周频率 BA 工作年度结束频率
M 月末频率 BAS 工作年度开始频率
SM 半月末频率 BH 工作小时频率
BM 工作月末频率 H 小时频率
MS 月初频率 T, min 分钟频率
SMS SMS半月初频率 S 秒钟频率
BMS 工作月初频率 L, ms 毫秒
Q 季度末频率 U, us 微秒
BQ 工作季度末频率 N 纳秒
QS 季度开始频率

Timedelta

Timedeltas是时间差,以不同的单位表示,例如天、小时、分钟、秒。它们可以是正数也可以是负数。

创建:

# 1. 字符串
pd.Timedelta('2 days 2 hours 15 minutes 30 seconds')

# 2. 整数
pd.Timedelta(6,unit='h')

# 3. 数据偏移量,如-周、天、小时、分钟、秒、毫秒、微秒、纳秒,也可以用于构建。
pd.Timedelta(days=2)

操作:

import pandas as pd

s = pd.Series(pd.date_range('2012-1-1', periods=3, freq='D'))
td = pd.Series([ pd.Timedelta(days=i) for i in range(3) ])
df = pd.DataFrame(dict(A = s, B = td))

# 1. 加法操作
df['C']=df['A']+df['B']

# 2. 减法操作
df['D']=df['C']-df['B']

# 3. 实际应用中,将时间索引作操作
pre_df.index = pre_df.index - pd.Timedelta(hours=20)

网站公告

今日签到

点亮在社区的每一天
去签到