pandas基础操作
DataFrame是pandas包中的重要数据类型,相当于表格数据类型,常用的操作如下:
创建DataFrame
import pandas as pd
#创建空DataFrame
df = pd.DataFrame()
#由List创建DataFrame
l = ['l1','l2','l3']
df = pd.DataFrame(l)
# 0
#0 l1
#1 l2
#2 l3
#由字典创建DataFrame
dict = {'name':['Jack','Rose','Three'],'number':['112','132','177'],'level':['low','high','mid']}
df = pd.DataFrame(dict)
# name number level
#0 Jack 112 low
#1 Rose 132 high
#2 Three 177 mid
DataFrame的切片、索引
1.获取某行数据
注意:.iloc后使用的是【中括号】
df.iloc[1]
#name Rose
#number 132
#level high
#Name: 1, dtype: object
df[1:2]
# name number level
#1 Rose 132 high
2.获取多行数据
注意:.iloc后使用的是两个【中括号】,若使用一个中括号得出的结果是取某一个元素。
#连续行
df[1:3]
# name number level
#1 Rose 132 high
#2 Three 177 mid
# 不连续行
df.iloc[[0,2]]
3.获取某列/多列数据
注意:.loc同样是两个【中括号】。
df['number']
df.loc[:,["name","level"]]
# name level
#0 Jack low
#1 Rose high
#2 Three mid
4.获取指定行/指定列
以下两者等价——.loc以行/列的名字获取,iloc以索引值方式获取。
df.loc[[1],["name","level"]]
df.iloc[[1],[0,2]]
5.获取满足某一条件的元素
data[data['v']>5
# !此时的v列必须是能比较的数据类型
DataFrame合并
这里直介绍简单的拼接:concat()函数,其使用两个DataFrame的Index进行拼接,不对应的地方会用NAN代替。
参数: axis=0(默认)是纵向拼接,axis=1横向拼接。
dict1 = {'name':['Jack','Rose','Three'],'number':['112','132','177'],'level':['low','high','mid']}
dict2 = {'name':['Terry','Matt'],'number':['112','132'],'level':['low','high']}
df1 = pd.DataFrame(dict1)
df2 = pd.DataFrame(dict2)
print(pd.concat([df1,df2],axis=1))
# name number level name number level
#0 Jack 112 low Terry 112 low
#1 Rose 132 high Matt 132 high
#2 Three 177 mid NaN NaN NaN
四则运算
加:+、add
减:-、sub
乘:*、mul
除:/、div
1.与数值
a = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9])
print(a+2)
2.与列表
可以是list、series类型
a = pd.DataFrame([[1, 2, 3], [4, 5, 6]],columns=['a', 'b', 'c'], index=['r1', 'r2'])
a.add([1, 2], axis=0) #按列加,列表长度需要等于数据框行数
a.add([1, 2, 3], axis=1) #按行加,列表长度需要等于数据框列数
3.某行/列与某行/列的运算
a = pd.DataFrame([1,2,3])
b = pd.DataFrame([2,5,3])
print(a.loc[:,0]*b.loc[:,0])
#0 2
#1 10
#2 9
#Name: 0, dtype: int64
4.与DataFrame
运算是根据行列索引进行的,相同列相同行(指行列索引)对应的数据做运算,不是共同拥有的行列索引也会保留下来,但是对应的结果为NaN。
问题: 由于行/列名的不同导致两DataFrame运算后的是NAN。
解决方法1: 在生成数据时,也生成相同的列名
df1 = pd.DataFrame(np.random.randn(3, 5), columns=['a', 'b', 'c', 'd', 'e'])
df2 = pd.DataFrame(np.random.random(df1.shape),columns=df1.columns)
print(df1+df2)
解决方法2: 使用np.array()函数转为numpy后运算。
df3 = pd.DataFrame(np.random.random(df1.shape))
df3 = np.array(df3)
print(df1+df3)
numpy基础操作
查找元素位置
np.where(condition,x,y) 返回numpy数组的索引值
import numpy as np
a=np.array([1,2,3,4,5])
print(np.where(a<3)) #查找小于3的元素的位置
print(np.where(a<3)) #(array([0, 1], dtype=int64),) turple类型
res = np.where(a<3)
print(res[0]) #[0, 1]
转置
a=np.array([[1,2,3],[4,5,6]])
print(a)
print(a.T)
矩阵乘法
矩阵数乘: a*b或者np.multiply(a,b)
a=np.array([[1,2,3],[4,5,6]])
b=np.array([[1,2,3],[4,5,6]])
print(a*b)
print(np.multiply(a,b))
矩阵乘法: a.dot(b)或者np.matmul(a,b)
a=np.array([[1,2],[4,5]])
b=np.array([[1,2,3],[4,5,6]])
print(np.matmul(a,b))
print(a.dot(b))
numpy/pandas/open3d/pyntcloud相互转换
pandas和numpy的互相转换
df转numpy的三种方法:np.array(df) ,df.values
a = pd.DataFrame([[1, 2, 3], [4, 5, 6]],columns=['a', 'b', 'c'], index=['r1', 'r2'])
b = np.array(a)
b = a.values
print(type(b)) # <class 'numpy.ndarray'>
numpy转df
c = pd.DataFrame(b,columns=['a', 'b', 'c'], index=['r1', 'r2'])
open3d与其他的互相转换
应用场景: 由于open3d不能直接读取txt格式的点云文件,因此需要用其他库读取点云后转为open3d,使用如下方法读取和转换:
1.pyntcloud读取
用到的函数有:
PyntCloud.from_file(path,name=[]) 生成pynt文件
文件.to_instance(“open3d”,mesh=False) pynt转open3d,默认mesh=True
PyntCloud.from_instance(“open3d”, 文件) open3d转pynt
import open3d as o3d
from pyntcloud import PyntCloud
pynt = PyntCloud.from_file('path/filenamee.txt', names=["x", "y", "z", "nx", "ny", "nz"])
print(type(point_cloud_pynt)) #<class 'pyntcloud.core_class.PyntCloud'>
print(type(point_cloud_pynt.points)) #<class 'pandas.core.frame.DataFrame'>
#pynt转open3d
pc_o3d = pynt.to_instance("open3d",mesh=False) # mesh=True by default
#open3d转pynt
original_triangle_mesh = o3d.io.read_triangle_mesh("diamond.ply")
cloud = PyntCloud.from_instance("open3d", original_triangle_mesh)
2.numpy读取
Numpy转DataFrame,DataFrame转pynt,pynt转Open3d
point_set = np.loadtxt('path/filename.txt',delimiter=',').astype(np.float32)
point_set = pd.DataFrame(point_set, columns = ["x", "y", "z", "nx", "ny", "nz"]) #np转df
pynt = PyntCloud(point_set) #df转pynt
o3d_pc = pynt.to_instance("open3d",mesh=False) #pynt转o3d
Numpy转Open3d
o3d.geometry.PointCloud()
o3d.utility.Vector3dVector(point_set)
point_set = np.loadtxt('path/filename.txt',delimiter=',').astype(np.float32)
point_set = point_set[:,0:3] #这行必须要有!!难道是因为只能是3列?
# np转o3d
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(point_set)
上述过程包含了多个转换,其余的以后用到再补充。根据作业一发现,使用不同数据类型的思路如下:
1.pynt读取.txt文件(也可以用numpy)
2.从pynt转为open3d方便可视化
3.pynt.points是 ‘pandas.core.frame.DataFrame’ 类型,可以使用pandas包对其进行操作。操作后可以使用pynt.points=df重新改变pynt,再转为o3d。
4.又或者将DataFrame转为Numpy类型,使用o3d.points = o3d.utility.Vector3dVector(points)或者o3d.normals = o3d.utility.Vector3dVector(normals)再保存为o3d类型,进行可视化等操作。
open3d常用函数
计算、显示法向量
#以下是两者不同方法
point_cloud_o3d.estimate_normals(
search_param=o3d.geometry.KDTreeSearchParamKNN(knn=15))
point_cloud_o3d.estimate_normals(
search_param=o3d.geometry.KDTreeSearchParamHybrid(0.2,9))
#point_show_normal=True用于显示法向量
o3d.visualization.draw_geometries([point_cloud_o3d],point_show_normal=True)
其他例子可参考链接写的很详细
索引
select_by_index(索引值list)函数
for_show = point_cloud_o3d.select_by_index(filtered_cloud)
可视化
pcd.paint_uniform_color([1, 0.706, 0]) # 修改点云颜色
o3d.visualization.draw_geometries([pcd], zoom=0.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024])
若想要聚类并显示为不同颜色,可使用list合并显示
l = []
for i in range(m):
pcd = o3d.geometry.PointCloud() #注意这行必须要写,不能放在for循环外面,否则会显示不完整
pcd.points = o3d.utility.Vector3dVector(origin_points[cluster_index==i])
pcd.paint_uniform_color(colors[i]) # 修改点云颜色
l.append(pcd)
o3d.visualization.draw_geometries(l)