几个dataframe的小trick

这篇博客分享了多个关于DataFrame的操作技巧,包括属性行获取、数据合并、删除空值和重复行、列类型转换、选择特定数值、计算距离、条件删除行、Spark数据处理、数据保存、分组运算、列转换、数据可视化以及根据条件过滤数据等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、获取属性行

id_list=df.columns.values.tolist()

2、两个dataframe合并,之后可以删除有空值的行,或者删除有重复的行

df3=pd.merge(df1,df2,how='left',on=['id'])

norepeat_df = df3.drop_duplicates(subset=['id'], keep='first')

nonan_df = norepeat_df.dropna(axis=0, how='any') 

3、object列转变为int64

df['id'] = df['id'].astype('int')

4、选择某个index行某个列对应的数值

df.loc[2511531]['lng']

5、两个相同的dataframe合并,依次计算目标值

for i in df_final.index.values:
    for j in df_final.index.values:
        dis=geodesic((df_final.loc[i]['center_lat'], df_final.loc[i]['center_lng']), (df_final.loc[j]['center_lat'], df_final.loc[j]['center_lng'])).km
        line1.append(i)
        line2.append(j)
        line3.append(dis)

6、删除满足特定条件的行

df = df.drop(df[(df.score < 50) & (df.score > 20)].index)

7、pyspark取数,保存为dataframe

导入相关的包

启动spark

sql='''sql语句'''

df1 = spark.sql(sql).toPandas()

8、将list存入txt,并以逗号分割

file = open("./park_ids.txt",'a')
for i in range(len(park_id_list)):
    s = str(park_id_list[i]).replace('[','').replace(']','')#去除[],这两行按数据不同,可以选择
    s = s.replace("'",'')+","   #去除单引号,每行末尾追加逗号
    file.write(s)
file.close()
9、groupby之后对每个分组中的两列做运算(比如求rmse、mape等)

数据长这样,目的是以city_id为分组依据,计算每个分组的in_list in_cnt之间的rmse

主要依据就是每个分组其实都可以按照一个dataframe来操作,遍历每个分组即可,本来想用transform或者apply来操作的,但是搞了半天没搞明白就放弃了,选择了这种写起来麻烦但是很容易理解的方式 

def compute_rmse(list1,list2):
    data={"a":list1,"b":list2}
    datafr=pd.DataFrame(data)
    datafr["er"]=abs((datafr["a"]-datafr["b"]))**2
    return (datafr["er"].mean())**0.5

def compute_mape(list1,list2):#list1为真实值,真实值不能为0
    data={"a":list1,"b":list2}
    datafr=pd.DataFrame(data)
    datafr["er"]=abs(((datafr["a"]-datafr["b"]))/datafr["a"])
    return (datafr["er"].mean())*100

city_id_list_20=df_in_20.city_id.unique()
print(len(city_id_list))
rmse_in_20=[]
for i in city_id_list_20:
    i=int(i)
    tmp=df_in_20.groupby(['city_id']).get_group(i)
    rmse_in_20.append(compute_rmse(tmp.in_cnt,tmp.in_list))
df_in_rmse_20=pd.DataFrame({"city_id":city_id_list_20,"rmse_20":rmse_in_20})
df_in_rmse_20.head()
df_in_rmse_20.to_csv("./df_in_rmse_20.csv",index=None)

10、将dataframe中的某一列数据转为float或者int64

import pandas as pd
df1['out_list'] = pd.to_numeric(df1['out_list'])#float

df1["hour"]=df1["hour"].values.astype(int)#int64

11、分组之后求每个分组的和(其实和8相比主要区别在于这里是对单列操作,8是对双列或者多列操作)

df5=pd.DataFrame(df4.groupby(["hour","logic_park_id","city_id"]).sum())
df5.head()
df5=df5.drop(columns=["origin_park_id"])
df5.reset_index(inplace=True)
df5.head()

12、删除df.ts_code大于等于"500000"且小于"600000"的所有行

df = df.drop(df[(df.ts_code >= "500000") & (df.ts_code < "600000")].index)

13、将dataframe的某一列转为datetime类型,并作差之后和实数作比较

import pandas as pd
df["op_time"]=pd.to_datetime(df["op_time"])
df["recommend_time"]=pd.to_datetime(df["recommend_time"])
df=df.drop(df[((df["op_time"]-df["recommend_time"])/np.timedelta64(1, "D")>1/12)|((df["op_time"]-df["recommend_time"])/np.timedelta64(1, "D")<0)].index)
df.head()

14、对dataframe某一列做折线图

15、groupby之后按照group进行绘图

ax=df8.groupby(["pt"]).get_group("2020-06-30").plot(x="put_park_id",y="active_data",kind="line",figsize=(12,8),color='green', label='2020-06-30')
df8.groupby(["pt"]).get_group("2020-07-01").plot(x="put_park_id",y="active_data",kind="line",ax=ax,figsize=(12,8),color='red', label='2020-07-01')

16、groupby之后对每个group求均值,并将均值赋给新列

def mean_time(group):
    group['link_ID_en'] = group['travel_time'].mean()
    return group

df = df.groupby('link_ID').apply(mean_time)
df.head()
 link_IDtime_interval_begintravel_timedatelengthwidthlink_classin_linksout_linkslinks_numarealink_ID_en
043779062898695005142017-04-01 06:00:001.0266722017-04-0157311.01.01.0,1.01711.117642
143779062898695005142017-04-01 06:02:001.0266722017-04-0157311.01.01.0,1.01711.117642
243779062898695005142017-04-01 06:04:001.0144542017-04-0157311.01.01.0,1.01711.117642
343779062898695005142017-04-01 06:06:001.0144542017-04-0157311.01.01.0,1.01711.117642
443779062898695005142017-04-01 06:08:001.0144542017-04-0157311.01.01.0,1.01711.117642

17、删除不想要的行

nonan_df=nonan_df.drop(nonan_df[~nonan_df["group_id"].isin(df1["group_id"])].index) 

18、合并分组

df_test=pd.DataFrame({"park_id":[],"pt":[],"out_cnt":[]})
for i in park_id_list:
    if df3.groupby('park_id').get_group(i).out_cnt.sum()>10:
        df_test=df_test.append(df3.groupby('park_id').get_group(i))

device = torch.device("cuda" if torch.cuda.is_available() else "cpu") ############################################ # 1. 数据预处理 ############################################ # 【1.1】读取数值型数据(用于原始数据分支) # 原来的数据预处理,替换 Y/N/?,并归一化;标签根据 list_y 得到索引。 list_y = ['WWW', 'MAIL','FTP-DATA', 'FTP-PASV','FTP-CONTROL','SERVICES','DATABASE' ,'P2P', 'ATTACK', 'MULTIMEDIA', 'INTERACTIVE', 'GAMES'] # 定义离散特征对应的列名和映射字典 feature_cols = ["col_65", "col_66", "col_67", "col_68", "col_71", "col_72"] label_mappings = { 'col_65': {'Y': 'Window_Scaling_cs', 'N': 'no_Window_Scaling_cs'}, 'col_66': {'Y': 'Time_Stamp_cs', 'N': 'no_Time_Stamp_cs'}, 'col_67': {'Y': 'Window_Scaling_sc', 'N': 'no_Window_Scaling_sc'}, 'col_68': {'Y': 'Time_Stamp_sc', 'N': 'no_Time_Stamp_sc'}, 'col_71': {'Y': 'SACK_cs', 'N': 'no_SACK_cs'}, 'col_72': {'Y': 'SACK_sc', 'N': 'no_SACK_sc'} } # 离散型特征在原始文件中的列索引(注意:索引从0开始) discrete_indices = [64, 65, 66, 67, 70, 71] def data_prepross_numeric(filenames): X, Y = [], [] for f in filenames: print("Processing numeric file:", f) with open(os.path.join(os.getcwd(), f), 'r') as file: # 跳过头部信息 for line in file.readlines()[253:]: #strip()去掉字符串两端的空格或换行符,确保处理后的字符串干净 # 保留原始行,不做 Y/N 替换,这里只做 strip(),后面我们会用离散规则进行过滤 line = line.strip().replace('?', '0') parts = line.split(',') row = [] # 对前面除标签外的所有列进行处理 for i, x in enumerate(parts[:-1]): if i in discrete_indices: # 离散型:直接保留原始字符串(如 "Y", "N", "?") row.append(x.strip()) else: # 其它列按 float 转换 row.append(float(x)) # 按原逻辑末尾补8个0(这部分可以认为是数值型数据) row.extend([0] * 8) # 标签处理,修正拼写错误后根据 list_y 得到索引 label = parts[-1].replace('FTP-CO0TROL', 'FTP-CONTROL') \ .replace('I0TERACTIVE', 'INTERACTIVE').strip() label_idx = list_y.index(label) X.append(row) Y.append(label_idx) # 注意:由于存在离散型列存为字符串,不能直接用 np.array(..., dtype=np.float32) # 此处返回原始列表和标签(标签可以转换为 numpy 数组) return X, np.array(Y) # 读取数据 filenames = ['MooreDataset/entry01.weka.allclass.arff'] X_raw, total_labels = data_prepross_numeric(filenames) # 将 X_raw 转换为 DataFrame方便后续处理 df_total = pd.DataFrame(X_raw) ############################################ # 2. 离散型特征处理与样本过滤 ############################################ # 从 df_total 中提取离散型部分:第65,66,67,68,71,72列(对应索引 64,65,66,67,70,71) df_discrete = df_total.iloc[:, discrete_indices].copy() df_discrete.columns = feature_cols # 加入 protocol 列(供检查使用) df_discrete["protocol"] = [list_y[label] for label in total_labels] # 对这六个离散列做映射:先用映射字典将 "Y"/"N" 转换为描述字符串 # (注意:原始数据中这些列应当只有 "Y", "N", 或 "?"(0)) for col in feature_cols: df_discrete[col] = df_discrete[col].map(label_mappings[col]) # 过滤掉任一离散型特征映射后为 NaN 的样本 df_discrete_valid = df_discrete.dropna(subset=feature_cols).reset_index(drop=True) valid_indices = df_discrete_valid.index # 接下来,将有效样本的离散型数据转换为数值: # 使用一个简单规则:映射描述性字符串还原为数字,"Window_Scaling_cs" 或其他描述中的肯定部分 → 1, # 而否定字符串(通常含 "no_") → 0. def discrete_to_num(x): if isinstance(x, str): if "no_" in x: return 0.0 else: return 1.0 else: return np.nan for col in feature_cols: df_discrete_valid[col] = df_discrete_valid[col].apply(discrete_to_num) # 现在 df_discrete_valid 中的离散列已经转换为数值(1.0 或 0.0)。 ############################################ # 3. 同步过滤原始数据并整合离散数据 ############################################ # 对 df_total(原始完整数据)按 valid_indices 同步过滤,得到有效样本 df_total_valid = df_total.loc[valid_indices].copy() # 将 df_total_valid 中原来存储离散型数据的对应列,替换为我们已经数值化的离散数据 for idx, col_name in zip(discrete_indices, feature_cols): df_total_valid.iloc[:, idx] = df_discrete_valid[col_name] # 此时 df_total_valid 的所有列均为数值型(离散列用 0/1 表示,其它列原样为 float,末尾有补的8个0) # 同时,将标签同步过滤 total_labels_filtered = total_labels[valid_indices] ############################################ # 4. 对过滤后的数据进行归一化(min-max归一化) ############################################ # 转换 df_total_valid 为 numpy 数组,并确保为 float32 total_x_filtered = df_total_valid.to_numpy(dtype=np.float32) X_min = np.min(total_x_filtered, axis=0) X_max = np.max(total_x_filtered, axis=0) X_range = X_max - X_min X_range[X_range == 0] = 1 X_norm_filtered = (total_x_filtered - X_min) / X_range # 输出结果检查 print("最终过滤后的数据形状:", X_norm_filtered.shape) print("最终过滤后的标签形状:", total_labels_filtered.shape) def data_prepross_as_string(filenames): X, Y = [], [] for f in filenames: print("Processing file:", f) with open(os.path.join(os.getcwd(), f), 'r') as file: # 假设需要跳过前253行头部信息 for line in file.readlines()[253:]: # 保留“Y”或“N”,将 '?' 替换为 "0" line = line.strip().replace('?', '0') parts = line.split(',') # 保留原始文本数据(离散部分不再转换为数值) features = parts[:-1] # 后面补充额外 8 个"0",与原来处理方式保持一致 features = features + ["0"] * 8 label = parts[-1].replace('FTP-CO0TROL', 'FTP-CONTROL').replace('I0TERACTIVE', 'INTERACTIVE') label_idx = list_y.index(label) X.append(features) Y.append(label_idx) X = np.array(X) return X, np.array(Y) 请你帮我分析我上述代码属于哪种转化方式?
最新发布
07-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值