pandas小知识

目录

遇到的问题

(1)TypeError: read_csv() got an unexpected keyword argument 'mangle_dupe_cols'

1.1 文件读取

(1) names和header

(2) usecols 用于指定取值列

(3) 全表读取 

1.2 文件保存

(1)常用方法

(2)使用ExcelWriter对象来在同一个Excel文件的不同Sheet中写入多个DataFrame。

1.3 pandas拼接

(1)常用方法:pd.concat

a、列名无重复

b、列名有重复

1)df1、df2有交叉重复列

 2)df3有重复列,无法和其他df拼接

3)df3、df4各自有重复列,但两者列名一模一样

(2)concat方法的join参数

1.4 df的value获取和转换

(1)value获取

(2)value类型转换:

numpy_array、list、tuple、dict

1.5  索引的修改

(1)行索引

(2)列索引

方案一:rename

方案二:遍历并重命名

1.6 切片 

(1)iloc 和 loc

a、相同点

b、不同点

(2)iat 和 at

a、相同点

b、不同点


遇到的问题

(1)TypeError: read_csv() got an unexpected keyword argument 'mangle_dupe_cols'

解决:https://github.com/huggingface/datasets/pull/5745
版本问题: 正解! pip install pandas==1.5.3

1.1 文件读取

(1) names和header

namesheader参数在pandas的read_excel函数中都是用来处理列名称的。

names 参数允许你为加载的数据框指定列名。这是一个字符串列表,长度应该等于数据框的列数。例如 names=['col1', 'col2', 'col3']。当你使用这个参数时,无论原始数据的列标题是什么,都会被替换成你指定的列名。

header 参数则是用来指定原始数据中哪一行作为列名。默认值是0,表示第一行是列名。如果你的数据没有列名,或者你不想使用原始数据的列名,你可以设置 header=None

所以,这两个参数的区别在于,names 是直接指定列名,而 header 是从原始数据中选择列名。

例如:

# 使用原始数据的第二行作为列名
pd.read_excel(read_path, header=1)

# 忽略原始数据的列名,指定新的列名
pd.read_excel(read_path, header=None, names=['col1', 'col2', 'col3'])
(2) usecols 用于指定取值列
# 只取表格中的‘问题’列,其他列不会取到
 df_new = pd.read_excel(read_path, sheet_name='new', usecols=['问题'])  
(3) 全表读取 
import pandas as pd

# 读取Excel文件
xls = pd.read_excel('filename.xlsx', sheet_name=None)

# xls现在是一个包含所有sheets的字典,键为sheet名,值为对应的DataFrame
for sheet_name, df in xls.items():
    print(f"Processing sheet: {sheet_name}")
    # 在这里你可以对df进行处理
    ...

1.2 文件保存

(1)常用方法

这种写法逻辑--先删后写:往同一个excel中插入数据时,即使不同的sheet名,也会默认先把之前已存在的sheet先删掉再写入新数据。

import pandas as pd

df1 = pd.DataFrame({
    'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],
    'B': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
    'C': [1, 2, 3, 4, 5, 6, 7, 8]
})

df2 = pd.DataFrame({
    'D': ['apple', 'banana', 'cherry', 'durian'],
    'E': ['red', 'yellow', 'red', 'green'],
    'F': [1, 2, 3, 4]
})
 
# 使用pd.DataFrame()函数将其转换为DataFrame
df = pd.DataFrame(datas1, columns=['request_id', 'question', 'answer', 'create_time', 'answer_is_gpt'])

# 数据写入excel
df.to_excel(out_path, sheet_name='问答', index=False)  
(2)使用ExcelWriter对象来在同一个Excel文件的不同Sheet中写入多个DataFrame。
import pandas as pd

df1 = pd.DataFrame({
    'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],
    'B': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
    'C': [1, 2, 3, 4, 5, 6, 7, 8]
})

df2 = pd.DataFrame({
    'D': ['apple', 'banana', 'cherry', 'durian'],
    'E': ['red', 'yellow', 'red', 'green'],
    'F': [1, 2, 3, 4]
})

# 创建一个ExcelWriter对象
with pd.ExcelWriter('output.xlsx') as writer:
    df1.to_excel(writer, sheet_name='Sheet1', index=False)
    df2.to_excel(writer, sheet_name='Sheet2', index=False)

# 在上面的代码中,我们首先创建了两个DataFrame df1 和 df2。然后,我们创建了一个ExcelWriter对象,并将这两个DataFrame分别写入到’output.xlsx’文件的’Sheet1’和’Sheet2’中。注意,我们使用了Python的with语句来自动关闭ExcelWriter,这是一个好的做法,可以确保所有的数据都被正确地写入文件。

1.3 pandas拼接

(1)常用方法:pd.concat

        pd.concat是pandas库中的一个函数,用于将两个或多个pandas对象(如Series,DataFrame)沿特定轴连接。此外,pd.concat还有很多其他参数,如join(设置连接方式,如’inner’,‘outer’),keys(创建分层索引)等,可以根据具体需求进行设置。具体见以下案例。

        注意,拼接的时候不管axis=0还是1,都是按行索引index一一对应拼接,比如:

import pandas as pd
import numpy as np

df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
                    'B': ['B0', 'B1', 'B2'],
                    'C': ['C0', 'C1', 'C2']})


################################# 1、不同行index的拼接【正确演示】
df1= df1.iloc[1:2, :-1]
print("df1: \n", df1)
# df1: 
#      A   B
# 1  A1  B1

# 重置行索引
df1.reset_index(drop=True, inplace=True)
print("df1: \n", df1)
# df1: 
#      A   B
# 0  A1  B1


df2 = pd.DataFrame(np.array([[''] * 3]), columns=['B1', 'C', 'D'])
print('df2 : \n', df2 )
# df2 : 
#    B1 C D
# 0       


df = pd.concat([df1, df2 ], axis=1)
print(df)
#     A    B   B1    C    D
# 0   A1   B1  NaN  NaN  NaN
         

可以看到df1的行索引最开始是1,经重置后改为0;df2也是0。按预期输出拼接后的结果。



################################# 2、不同行index的拼接【错误演示】
df1= df1.iloc[1:2, :-1]
print("df1: \n", df1)
# df1: 
#      A   B
# 1  A1  B1


df2 = pd.DataFrame(np.array([[''] * 3]), columns=['B1', 'C', 'D'])
print('df2 : \n', df2 )
# data_frame: 
#    B1 C D
# 0       


df = pd.concat([df1, df2 ], axis=1)
print(df)
#     A    B   B1    C    D
# 1   A1   B1  NaN  NaN  NaN
# 0  NaN  NaN               

可以看到df1的行索引是1,df2则是0,拼接后的结果是0,1各一行
a、列名无重复
import pandas as pd

# 案例1:创建两个DataFrame
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                    'B': ['B0', 'B1', 'B2', 'B3'],
                    'C': ['C0', 'C1', 'C2', 'C3'],
                    'D': ['D0', 'D1', 'D2', 'D3']},
                   index=[0, 1, 2, 3])

df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
                    'B': ['B4', 'B5', 'B6', 'B7'],
                    'C': ['C4', 'C5', 'C6', 'C7'],
                    'D': ['D4', 'D5', 'D6', 'D7']},
                   index=[4, 5, 6, 7])

# 沿着行轴(axis=0)连接这两个DataFrame
result = pd.concat([df1, df2])

print(result)


# 在这个例子中,pd.concat将df1和df2沿着行轴(即垂直方向)连接了起来,因为默认的axis参数值是0。
# 你也可以通过设置axis参数为1来沿列轴(即水平方向)连接DataFrame:
result = pd.concat([df1, df2], axis=1)


# 案例2:给空df拼接数据
df_new = pd.DataFrame()

# 创建一个1行3列的数据
df_tmp = pd.DataFrame(np.array([['aa', 'bb', 'cc']]))

# 加入新的数据表
df_new = pd.concat([df_new, df_tmp], axis=0)
b、列名有重复
1)df1、df2有交叉重复列

df1和df2都有a、b列,但可以正常拼接。

 2)df3有重复列,无法和其他df拼接

因为df3的列索引abcab中ab列重复,所以导致df3无法与df1进行concat堆叠。这种就需要用到“1.5中列索引的修改

3)df3、df4各自有重复列,但两者列名一模一样

df3和df4可以正常拼接,这是因为:虽然df3,df4的列索引abcab中ab列重复,但是df3,df4的列索引相同,所以concat也能正常运行,这就是例外情况。 

(2)concat方法的join参数

join参数在pandas.concat函数中用于指定连接的方式。有两个选项,‘inner’和’outer’。

‘outer’:这是默认的连接方式,它会返回所有的行,并且会用NaN来填充那些在某些数据中不存在的列的值。

‘inner’:这种方式只会返回那些在所有数据中都有的行,并且只包含那些在所有数据中都存在的列。

import pandas as pd

df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
                    'B': ['B0', 'B1', 'B2'],
                    'C': ['C0', 'C1', 'C2']},
                   index=[1, 2, 3])

df2 = pd.DataFrame({'B': ['B2', 'B3', 'B4'],
                    'C': ['C2', 'C3', 'C4'],
                    'D': ['D2', 'D3', 'D4']},
                   index=[2, 3, 4])

############方案1:外连接
result_outer = pd.concat([df1, df2], join='outer')
print(result_outer)

##输出(注意NaN值):

     A   B   C    D
1   A0  B0  C0  NaN
2   A1  B1  C1  NaN
3   A2  B2  C2  NaN
2  NaN  B2  C2   D2
3  NaN  B3  C3   D3
4  NaN  B4  C4   D4



############ 方案2:内连接

result_inner = pd.concat([df1, df2], join='inner')
print(result_inner)

## 输出(只包含共同的列和行):

    B   C
1  B0  C0
2  B1  C1
3  B2  C2
2  B2  C2
3  B3  C3
4  B4  C4

1.4 df的value获取和转换

(1)value获取
  • 如果你想获取整个DataFrame或者某一列的值,可以使用以下代码:
values = df['column_name']
  •  要获取某一列 不重复的 非空值(非None 或 nan)
unique_values = df['column_name'].dropna().unique()
  • 要获取整个DataFrame的值,可以使用.values属性:
values = df['column_name'].values

这将返回一个NumPy数组,其中包含DataFrame中的所有值。

(2)value类型转换:
numpy_array、list、tuple、dict
  •  numpy_array
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
                    'B': ['B0', 'B1', 'B2'],
                    'C': ['C0', 'C1', 'C2']})

# 1、获取values,结果是numpy.array类型
datas_array = df1.values  
print(datas_array)
# [['A0' 'B0' 'C0']
#  ['A1' 'B1' 'C1']
#  ['A2' 'B2' 'C2']]
  • list
# 2、转list类型
data_list = df1.values.tolist()  
print(data_list )
# [['A0', 'B0', 'C0'], ['A1', 'B1', 'C1'], ['A2', 'B2', 'C2']]
  •  tuple
# 3、转tuple类型
# 方案一:
tuples = [tuple(x) for x in df1.values]
print(tuples)
# [('A0', 'B0', 'C0'), ('A1', 'B1', 'C1'), ('A2', 'B2', 'C2')]

# 方案二:
# 将DataFrame的值转换为元组
for row in df1.itertuples(index=False):
    print(row)

# Pandas(A='A0', B='B0', C='C0')
# Pandas(A='A1', B='B1', C='C1')
# Pandas(A='A2', B='B2', C='C2')
  • dict

xx_df.to_dict(orient="records")这个函数调用做的事情是将xx_df DataFrame的每一行转换为一个字典,然后将这些字典放在一个列表中。

orient="records"参数指定了字典的键应该是DataFrame的列名,每个键的值应该是该列在特定行中的值。

import pandas as pd

data = {'Name': ['John', 'Anna'], 'Age': [28, 23]}
df = pd.DataFrame(data)

print(df)

输出:

   Name  Age
0  John   28
1  Anna   23

执行to_dict(orient="records")将它转换为字典列表:

print(df.to_dict(orient='records'))

 输出:[{'Name': 'John', 'Age': 28}, {'Name': 'Anna', 'Age': 23}]
每个字典代表DataFrame的一行,字典的键是列名,值是该行在该列的值。

1.5  索引的修改

(1)行索引

使用DataFrame的reset_index()方法重置行索引。如果你想要重置行索引为默认值(即从0开始的整数),你可以通过reset_index()和drop=True参数来实现:

import pandas as pd

# 创建一个DataFrame
df = pd.DataFrame({
    'A': ['foo', 'bar', 'baz'],
    'B': ['one', 'two', 'three'],
    'C': [1, 2, 3]
}, index=['x', 'y', 'z'])

print("Before reset index:")
print(df)

# 重置索引
df_reset = df.reset_index(drop=True)

print("After reset index:")
print(df_reset)

以上例子中,我们首先创建了一个索引为’x’, ‘y’, 'z’的DataFrame。然后,我们使用reset_index(drop=True)方法重置索引。drop=True参数表示我们不希望保留原来的索引。如果你希望在重置索引的同时保留原来的索引,你可以省略这个参数。

请注意,reset_index()方法不会在原地修改DataFrame,而是返回一个新的DataFrame。如果你想要在原地修改DataFrame,你可以添加inplace=True参数:

df.reset_index(drop=True, inplace=True)
(2)列索引
方案一:rename

df.rename(columns=columns, inplace=True)这个命令的作用是重命名DataFrame的列名。columns参数应该是一个字典,其中键是旧的列名,值是新的列名。

df = pd.DataFrame({
    'A': ['A0', 'A1', 'A2'],
    'B': ['B0', 'B1', 'B2']
})

df.rename(columns={'A': 'a', 'B': 'b'}, inplace=True)

在这个例子中,df.rename(columns={'A': 'a', 'B': 'b'}, inplace=True)将列名’A’改为’a’,列名’B’改为’b’。 

方案二:遍历并重命名

如果DataFrame中有重复的列名,你可以通过遍历列名并添加后缀的方式进行重命名。

import pandas as pd

# 创建一个有重复列名的DataFrame
df = pd.DataFrame([[1, 2, 3, 4], [5, 6, 7, 8]], columns=['A', 'B', 'A', 'B'])

# 创建一个空字典,用于存储新的列名
new_columns = {}

for col in df.columns:
    if col not in new_columns:
        new_columns[col] = col
    else:
        i = 1
        while f"{col}_{i}" in new_columns:
            i += 1
        new_columns[f"{col}_{i}"] = col

# 重命名列名
df.rename(columns=new_columns, inplace=True)

print(df)

1.6 切片 

(1)iloc 和 loc
a、相同点

使用df.iloc[]或df.loc[]提取单行数据时,返回的是一个Series对象。

而当提取多行数据时,返回的是一个DataFrame对象。

举例来说:

import pandas as pd

df = pd.DataFrame({
    'A': ['A0', 'A1', 'A2'],
    'B': ['B0', 'B1', 'B2']
})

print(type(df.iloc[0]))  # <class 'pandas.core.series.Series'>
print(type(df.iloc[0:2]))  # <class 'pandas.core.frame.DataFrame'>
在这个例子中,当我们提取第一行数据(df.iloc[0])时,返回的是一个Series对象。而当我们提取第一行和第二行数据(df.iloc[0:2])时,返回的是一个DataFrame对象。

如果你希望即使只提取一行数据,也返回DataFrame对象,你可以使用切片的方式,如df.iloc[0:1],这样即使只提取一行数据,也会返回DataFrame对象。

注意:Series对象在拼接时会报错,所以切片最好指定start和end。

b、不同点
  • .loc[] 需要你提供行标签和列标签(也就是行和列的名称):
df.loc[row_label, 'column_name'] = new_value
  • .iloc[] 需要你提供行索引和列索引(也就是行和列的位置):
df.iloc[row_index, column_index] = new_value

其中 new_value 是你想要赋给这个单元格的新值。

如果你想给整个列赋值,你可以直接使用列的名称:

df['column_name'] = new_value

这会将 new_value 赋值给 column_name 这一列的所有单元格。如果 new_value 是一个列表或数组,那么它的长度必须和 DataFrame 的行数相同。

(2)iat 和 at
a、相同点

都可以获取excel中指定单元格的值。

b、不同点
  • at方法用于通过行标签和列标签(即行和列的名称)获取值,如:
value = df.at[0, 'column_name']
  • iat方法用于通过行索引和列索引(即行和列的位置)获取值,如:
value = df.iat[0, 0]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值