# Pandas Notes

## CSV related

### 读取 CSV

```python
pd.read_csv(filepath_or_buffer, sep, header, parse_dates, index_col, prefix, encoding)
```

参数： **filepath\_or\_buffer**: 字符串，或者任何对象的read()方法。这个字符串可以是URL，有效的URL方案包括http、ftp、s3和文件。可以直接写入"文件名.csv"。\
**sep**: 分隔符，默认为 ','\
**header**: 将行号用作列名，且是数据的开头。默认为0，即将读取的第一行作为每一列的列名。\
注意当 **skip\_blank\_lines=True** 时，这个参数忽略注释行和空行。所以header=0表示第一行是非空的数据而不是文件的第一行。若令 `header=None` 则第一行被当作数据，df的列名为序号 1,2,3...\
**parse\_dates**: 布尔类型值 or int类型值的列表 or 列表的列表 or 字典（默认值为 FALSE）\
1\. True:尝试解析索引\
2\. 由int类型值组成的列表(如\[1,2,3]):作为单独数据列，分别解析原始文件中的1,2,3列\
3\. 由列表组成的列表(如\[\[1,3]]):将1,3列合并，作为一个单列进行解析\
4\. 字典(如{'foo'：\[1, 3]}):解析1,3列作为数据，并命名为foo

**squeeze**: 布尔值，默认FALSE\
TRUE 如果被解析的数据只有一列，那么返回 **Series** 类型。\
**prefix**: 给列名加的前缀\
**encoding**: 导入出现乱码的时候使用，常用的有 'utf-8', 'gbk'

### 写入 CSV

```python
dataframe.to_csv(path_or_buf,sep,na_rep,mode,columns,header,index)
```

参数：\
**path\_or\_buf**: 字符串，放文件名、相对路径、文件流等；\
**sep**: 字符串，分隔符，跟read\_csv()的一个意思\
**na\_rep**: 字符串，将NaN转换为特定值\
**mode**: 默认模式是覆盖写，当 `mode='a'` 为**追加写**\
**columns**: 列表，指定哪些列写进去\
**header**: 默认header=0，如果没有表头，设置header=None\
**index**: 关于索引的，默认True，写入索引

## Dataframe

### list 转化 dataframe

```python
a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]  
df = pd.DataFrame(a, columns=['one', 'two', 'three'])
```

### DataFrame 转 Numpy

```python
df=pd.DataFrame(xxx)

# 三种方式
1. df.values # Not Callable
2. df.as_matrix()
3. np.array(df)
```

### Numpy 转 DataFrame

```python
mat = np.random.rand(3, 4)

df = pd.DataFrame(mat, columns=('colA', 'colB', 'colC', xxx)) # 给列命名
```

### 插入一行

貌似没有直接的插入选项，但是可以通过每次新建一个临时的 `pd.DataFrame` 然后 `df.append()` 实现操作：

```python
df = pd.DataFrame(columns=('name', 'sex', 'id'))
name = '小王'
sex = '男'
id = '001'
df = df.append(pd.DataFrame({'name':[name],'sex':[sex],'id':[id]}), ignore_index=True)
```

几点重要的地方：\
1\. DataFrame.append() 不会对自己产生改变，要在前面加上 df= 。\
2\. append() 内部其实就是临时新建了一个实例，这里新建实例的方法是采用字典的方式 `{'attr':[val], xxx }` 对于每个属性后面跟上初始化的赋值 val，注意 val 要用 \[] 括起来。\
3\. 要加上 `ignore_index=True` 否则可能新建的实例会有自带的索引导致多出一列，append之后得不到自己想要的结果。

### 遍历元素

例子:

```python
   c1  c2  
0  10  100  
1  11  110  
2  12  120
```

#### Dataframe.iterrows()

按行遍历，将 DataFrame 的**每一行**迭代为 (index, Series) 对，可以通过 `row[name]` 对元素进行访问。

```python
>>> for index, row in df.iterrows():
...     print(index)
...     print(row['c1'], row['c2'])
...

Output: 
0
(10, 100)
1
(11, 110)
2
(12, 123)
```

#### Dataframe.itertuples()

按行遍历，将 DataFrame 的**每一行**迭代为元组(tuple)，可以通过 `getattr(row, name)` 对元素进行访问，比 iterrows() **效率高**。

```python
>>> for row in df.itertuples():
...     print(getattr(row, 'c1'), getattr(row, 'c2'))
...

Output: 
(10, 100)
(11, 110)
(12, 123)
```

#### Dataframe.iteritems()

按列遍历，将DataFrame的**每一列**迭代为 **(列名, Series)** 对，可以通过 row\[index] 对元素进行访问。

```python
>>> for index, row in df.iteritems():
...     print(index)
...     print(row[0], row[1], row[2])
...

Output:
c1
(10, 11, 12)
c2
(100, 110, 123)
```

### 选取某一列或某一行

```python
data['w']    #选择表格中的'w'列，使用类字典属性，返回的是 Series 类型

data.w       #选择表格中的'w'列，使用点属性，返回的是 Series 类型

data[['w']]  #选择表格中的'w'列，返回的是 DataFrame 类型

data[0:2]  #返回第1行到第2行的所有行，前闭后开，包括前不包括后

data[1:2]  #返回第2行，从0计，返回的是单行，通过有前后值的索引形式，
           #如果采用data[1]则报错，data[1:1]返回为空

data.iloc[-1]   #选取DataFrame最后一行，返回的是 Series
data.iloc[-1:]  #选取DataFrame最后一行，返回的是 DataFrame
```

### 给某列更名

1. 读取文件的时候重命名 names = new\_col，可以在读取文件的时候，给出新列名。  &#x20;

   ```python
   new_col = ['new1', 'new2',... , 'newn']
   pd.read_csv('data', names = new_col, header=0)
   ```
2. 全部重命名 columns = new\_columns，新列名的长度必须与旧列名**一致**. &#x20;

   ```python
   new_col = ['new1', 'new2',... , 'newn']
   dataframe.columns = new_col
   ```
3. 部分重命名 columns = dict，使用**字典类型的数据**对列进行重命名。  &#x20;

   ```python
   dataframe.rename(columns = {"old_name": "new_name"})
   dataframe.rename(columns = {"old1": "new1", "old2":"new2"},  inplace=True)
   ```
4. 因为dataframe的columns就是string类，所以可以直接使用 str.replace &#x20;

   ```python
   dataframe.columns = dataframe.columns.str.replace('' '', ''_'')
   ```

### 拼接操作

#### pandas.concat()

pandas 的顶级方法，提供了axis设置可用于 dataframe 间**行方向**（增加行，下同）或**列方向**（增加列，下同）进行内联或外联拼接操作。

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

参数说明:\
**objs**: 需要进行拼接的对象的集合，要用 `[]` 框起来 **axis**: 拼接轴方向，默认为0，沿行拼接；若为1，沿列拼接\
**join**: 默认外联'outer'，拼接另一轴所有的label，缺失值用NaN填充；内联'inner'，只拼接另一轴相同的label；\
**join\_axes**: 指定需要拼接的轴的labels，可在join既不内联又不外联的时候使用\
**ignore\_index**: 对index进行重新排序\
**keys**: 多重索引

#### Dataframe.append()

dataframe 数据类型的方法，提供了**行方向**的拼接操作。

```python
append(self, other, ignore_index=False, verify_integrity=False)
```

常用参数说明:\
**other**: 另一个dataframe\
**ignore\_index**: 若为True，则对index进行重排\
**verify\_integrity**: 对index的**唯一性进行验证**，若有重复，报错。若已经设置了ignore\_index，则该参数无效

#### Dataframe.join()

dataframe 数据类型的方法，提供了**列方向**的拼接操作，支持**左联、右联、内联和外联**四种操作类型。

```python
join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
```

常用参数说明:\
**on**: 参照的左边df列名key（可能需要先进行set\_index操作），若未指明，按照index进行join\
**how**: {'left', 'right', 'outer', 'inner'}

* 默认'left'，即按照左边df的index(若声明了on，则按照对应的列)； &#x20;
* 若为'right' 则按照右边的df；
* 若'inner'为内联方式；
* 若为'outer'为全连联方式。 &#x20;

**sort**: 是否按照join的key对应的值大小进行排序，默认False\
**lsuffix**，**rsuffix**: 当left和right两个df的列名出现冲突时候，通过设定后缀的方式避免错误

#### Dataframe.merge()

pandas 的顶级方法，提供了类似于 SQL 数据库连接操作的功能，支持**左联、右联、内联和外联**等全部四种SQL连接操作类型。

```python
pd.merge(left, 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,
          validate=None):
```

既可作为pandas的顶级方法使用，也可作为DataFrame数据结构的方法进行调用\
常用参数说明:\
**how**: {'left', 'right', 'outer', 'inner'}

* 默认'inner'，类似于SQL的内联； &#x20;
* 'left' 类似于SQL的左联；  &#x20;
* 'right' 类似于SQL的右联； &#x20;
* 'outer' 类似于SQL的全联。 &#x20;

**on**: 进行合并的参照列名，必须一样。若为None，方法会自动匹配两张表中相同的列名\
**left\_on**: 左边df进行连接的列\
**right\_on**: 右边df进行连接的列\
**suffixes**: 左、右列名称前缀\
**validate**: 默认None

* "one\_to\_one" ，验证是否一对一关系 &#x20;
* "one\_to\_many" ，验证是否一对多关系 &#x20;
* "many\_to\_one"，验证是否多对一关系 &#x20;
* "many\_to\_many"，验证是否多对多关系 &#x20;

SQL语句复习:

```sql
内联: SELECT a.*, b.* from table1 as a inner join table2 as b on a.ID=b.ID
左联: SELECT a.*, b.* from table1 as a left join table2 as b on a.ID=b.ID
右联: SELECT a.*, b.* from table1 as a right join table2 as b on a.ID=b.ID
全联: SELECT a.*, b.* from table1 as a full join table2 as b on a.ID=b.ID
```

### 删除某一行或某一列

```python
dataframe.drop(label=['xxx','xxx','xxx'], axis=0, inplace=False)
```

参数：\
**label**: 是指定要删除的列或行的行号或列名称\
**axis**: 删除的轴，默认为0，沿行方向进行删除，axis=1为沿列方向进行删除\
**inplace**: 这个函数返回的是修改后的dataframe 但并不会改变自身，inplace=True的时候可以同时对自身进行修改

### 求交并差集

对于colums都相同的dataframe做过滤的时候，例如：

```python
df1 = DataFrame([['a', 10, '男'], 
                 ['b', 11, '男'], 
                 ['c', 11, '女'], 
                 ['a', 10, '女'],
                 ['c', 11, '男']], 
                columns=['name', 'age', 'sex'])

df2 = DataFrame([['a', 10, '男'], 
                 ['b', 11, '女']],
                columns=['name', 'age', 'sex'])
```

#### 取交集

```python
print(pd.merge(df1,df2,on=['name', 'age', 'sex']))
```

#### 取并集

```python
print(pd.merge(df1,df2,on=['name', 'age', 'sex'], how='outer'))
```

#### 取差集

差集即从df1中过滤df1在df2中存在的行\
**思路**：将df2两次合并到df1中，然后删除重复项。\
**为什么要合并两次？** 因为合并一次会求出对称差 ((A-B)$\cup$(B-A)) ，两次就能够将对称差中的 df2 也变成重复项从而删除掉。

```python
df1 = df1.append(df2)  # 合并第一次
df1 = df1.append(df2)  # 合并第二次
df1 = df1.drop_duplicates(subset=['name', 'age', 'sex'],keep=False)
print(df1)
```

### pandas 常用函数

#### DataFrame.drop\_duplicates

| Parameters | Effect                                                                                                                                                                                                                                                                                      |
| :--------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   subset   | <p>column label or sequence of labels, optional<br>Only consider certain columns for identifying duplicates, <strong>by default use all of the columns</strong></p>                                                                                                                         |
|    keep    | <p>{<strong>'first', 'last', False</strong>}, default <strong>'first'</strong><br><strong>first</strong> : Drop duplicates except for the first occurrence.<br><strong>last</strong> : Drop duplicates except for the last occurrence.<br><strong>False</strong> : Drop all duplicates.</p> |
| take\_last | *deprecated*                                                                                                                                                                                                                                                                                |
|   inplace  | <p><strong>boolean</strong>, default <strong>False</strong><br>Whether to drop duplicates in place or to return a copy</p>                                                                                                                                                                  |
|    cols    | kwargs only argument of subset \[*deprecated*]                                                                                                                                                                                                                                              |

**Returns**: deduplicated: DataFrame

e.g.

```python
df=pd.DataFrame(xxx)
df.drop_duplicates(subset=['id','name'], keep=False) # 根据id和name双重判断，重复的一个都不留
df.drop_duplicates(subset=['id'], inplace=True) # 根据id判断，只留下第一个找到的重复值，并且赋值给自身
```

#### Series.groupby

|  Parameters | Effect                                                                                                                                                                                                                                                                                                        |
| :---------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|     axis    | <p><strong>int</strong>, <strong>default 0</strong> <br> 0 for row <br> 1 for col</p>                                                                                                                                                                                                                         |
|     sort    | <p><strong>boolean</strong>, <strong>default True</strong> <br> Sort group keys. <br> Get better performance by turning this off. <br> Note this does not influence the order of observations within each group. groupby <strong>preserves the order</strong> of rows <strong>within</strong> each group.</p> |
| group\_keys | <p><strong>boolean</strong>, <strong>default True</strong> <br> When calling apply, <strong>add group keys</strong> to index to identify pieces.</p>                                                                                                                                                          |
|   squeeze   | <p><strong>boolean</strong>, <strong>default False</strong> <br> reduce the dimensionality of the return type if possible, otherwise return a consistent type</p>                                                                                                                                             |

**Returns**: GroupBy object

**注意**：这里的 groupby 的调用函数是 Series 不是 DataFrame，而 DataFrame需要通过 df\['col'] 取值得到 Series。\
**注意**：这里返回的是 Series 格式，只包括 **被筛选的列** 和 **key列**

e.g.

```python
# 一条记录有 id name commit_time
# 现在需要找到每个学生的最晚提交时间
# 由于 commit_time 是 date 格式所以可以直接比较大小
# 思路：根据id和name将所有commit_time进行分组然后取组内最大  
res = df['commit_time'].groupby([df['id'], df['name']]).max()  
或 res = df[['name', 'commit_time']].groupby(df['id']).max()
```

## Reference

1. [csdn | pandas按行按列遍历Dataframe的几种方式](https://blog.csdn.net/sinat_29675423/article/details/87972498) &#x20;
2. [csdn | 取dataframe的一列或一行](https://blog.csdn.net/m0_37876745/article/details/88828928) &#x20;
3. [csdn | Pandas中的拼接操作(concat,append,join,merge)](https://blog.csdn.net/guofei_fly/article/details/85455813) &#x20;
4. [简书 | pandas读取文件的read\_csv()](https://www.jianshu.com/p/ebb64a159104) &#x20;
5. [cnblogs | Pandas 通过追加方式合并多个csv](https://www.cnblogs.com/bigtreei/p/9946072.html) &#x20;
6. [cnblogs | pd.read\_csv() 、to\_csv() 之 常用参数](https://www.cnblogs.com/wyy1480/p/10322336.html) &#x20;
7. [cnblogs | 给DataFrame的列命名或重命名](https://www.cnblogs.com/wqbin/p/11590425.html) &#x20;
8. [cnblogs | pandas DataFrame行或列的删除方法](https://www.cnblogs.com/datasnail/p/9767158.html) &#x20;
9. [csdn | pandas: DataFrame 交集并集补集](https://blog.csdn.net/qq_40981268/article/details/85957177) &#x20;
10. [csdn | list 转化 dataframe](https://blog.csdn.net/ls13552912394/article/details/80317905) &#x20;
11. [csdn | Pandas创建一个空DataFrame，并逐行插入数据](https://blog.csdn.net/roamer314/article/details/80886075) &#x20;
12. [pandas 0.17.0 documents](https://pandas.pydata.org/pandas-docs/version/0.17.0/api.html) &#x20;
13. [cnblogs | python中groupby函数详解](https://www.cnblogs.com/Yanjy-OnlyOne/p/11217802.html)  &#x20;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://legacy.cookielau.com/archives/3-python/2-library/1-pandasnotes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
