如何修改Python DataFrame的for循环与if语句,按Total列条件提取数据
问题描述
我尝试用for循环和if语句对Pandas DataFrame设置条件提取数据行,CSV格式不规范,已经手动设置列名:['Nama', 'Jabatan', 'Alamat', 'Klasifikasi Saham', 'Jumlah Lembar Saham', 'Total']。已知df.iloc[0:23]是高管数据,df.iloc[24:42]是股东数据,但把逻辑放进for循环后无法正常返回结果。需求是创建函数:当Total列值为'-'时返回高管数据,Total列非空时返回股东数据,该怎么修改for循环和if语句?
原代码如下:
import pandas as pd input_csv_file = "./CSV/Officers_and_Shareholders.csv" df = pd.read_csv(input_csv_file, skiprows=10, on_bad_lines='skip') df.fillna('', inplace=True) # df.drop([0, 3], inplace=True) df.columns = ['Nama', 'Jabatan', 'Alamat', 'Klasifikasi Saham', 'Jumlah Lembar Saham', 'Total'] # print(df.shape) # print(df.columns) # print(df.iloc[:53]) # shareholders = df.iloc[24:42] # print(shareholders) # officers = df.iloc[0:23] # print(officers) dataframe = df.query("Total.ne('-')") def get_shareholder_by_row_index(): for column in df.columns: if object(df.iloc[column][:53]) == dataframe: shareholders = df.iloc[24:42] print(shareholders) # elif object(df[:53][column]) != dataframe: # officers = df.iloc[0:23] # print(officers)
期望股东数据输出:
24 PT CTCORP INFRASTRUKTUR D INDONESIA, ... Rp. 3.200.000.000 25 Nomor SK :- I ... 26 JalanKaptenPierreTendeanKavling12-14A ... 27 PT INTRERPORT PATIMBAN AGUNG, ... Rp. 2.900.000.000 28 Nomor SK :- ... 29 ... 30 ... 31 ... 32 ... 33 ... 34 PT PATIMBAN MAJU BERSAMA, ... Rp. 2.900.000.000 35 Nomor SK :AHU- ... 36 0061318.AH.01.01.TAHUN 2021 ... 37 Tanggal SK :30 September 2021 ... 38 ... 39 ... 40 PT TERMINAL PETIKEMAS ... Rp. 1.000.000.000 41 SURABAYA, ... 42 Nomor SK :- ...
期望高管数据输出:
Nama ... Total 1 NIK: 3171060201830005 ... 2 NPWP: 246383541071000 ... 3 TTL: Jakarta, 02 Januari 1983 ... 5 NIK: 1271121011700003 ... 6 NPWP: 070970173112000 ... 7 TTL: Bogor, 10 November 1970 ... 8 ARLAN SEPTIA ANANDA ... 9 RASAM, ... 10 NIK: 3174051209620003 ... 11 NPWP: 080878200013000 ... 12 TTL: Jakarta, 12 September ... 13 1962 ... 15 NIK: 3171011605660004 ... 16 NPWP: 070141650093000 ... 17 TTL: Jakarta, 16 Mei 1966 ... 18 FUAD RIZAL, ... 21 PURNOMO, UTAMA RASRINIK: 3578032408610001 ... 22 NPWP: 097468813615000 ... 23 TTL: SLEMAN, 24 Agustus 1961 ...
解决方案
原代码问题分析
- 循环遍历列名完全没必要,需求是基于
Total列的行值筛选,和列无关 df.iloc[column]用法错误,iloc接收行索引,列名应使用df[column]- 直接用
object(...) == dataframe比较DataFrame无效,DataFrame不能直接判断相等
优化后的高效实现(推荐)
不需要用for循环,直接利用Pandas布尔索引筛选,同时结合已知行范围做双重验证(避免CSV格式不规范导致单条件筛选出错):
import pandas as pd input_csv_file = "./CSV/Officers_and_Shareholders.csv" df = pd.read_csv(input_csv_file, skiprows=10, on_bad_lines='skip') df.fillna('', inplace=True) df.columns = ['Nama', 'Jabatan', 'Alamat', 'Klasifikasi Saham', 'Jumlah Lembar Saham', 'Total'] def get_data_by_total_condition(): # 筛选高管:Total为'-' 且 在已知高管行范围内 officers = df[(df['Total'] == '-') & (df.index.isin(range(0,23)))] # 筛选股东:Total非空且不是'-' 且 在已知股东行范围内 shareholders = df[(df['Total'] != '-') & (df['Total'] != '') & (df.index.isin(range(24,43)))] return officers, shareholders # 调用函数并打印结果 officers_data, shareholders_data = get_data_by_total_condition() print("=== 高管数据 ===") print(officers_data) print("\n=== 股东数据 ===") print(shareholders_data)
若坚持使用for循环实现(不推荐,效率低)
如果一定要用循环遍历行判断,代码如下:
def get_data_with_loop(): officers = [] shareholders = [] for idx, row in df.iterrows(): # 结合行范围和Total列值判断 if 0 <= idx <23 and row['Total'] == '-': officers.append(row) elif 24 <= idx <=42 and row['Total'] != '-' and row['Total'] != '': shareholders.append(row) # 转换为DataFrame返回 return pd.DataFrame(officers), pd.DataFrame(shareholders) # 调用函数 officers_loop, shareholders_loop = get_data_with_loop() print(officers_loop) print(shareholders_loop)
说明
- 优先使用Pandas原生布尔索引,比循环高效得多,数据量大时差异更明显
- 同时结合行索引范围和
Total列值,是因为CSV格式不规范,双重验证能避免误判 - 原代码中的
df.query("Total.ne('-')")可简化为df[df['Total'] != '-'],更直观
内容的提问来源于stack exchange,提问作者htrgotoh
相关产品推荐
相关产品推荐

