选择每第 n 行作为 Pandas DataFrame 而无需读取整个文件
Posted
技术标签:
【中文标题】选择每第 n 行作为 Pandas DataFrame 而无需读取整个文件【英文标题】:Select every nth row as a Pandas DataFrame without reading the entire file 【发布时间】:2019-05-17 15:14:47 【问题描述】:我正在读取一个包含约 950 万行 x 16 列的大文件。
我对检索有代表性的样本感兴趣,并且由于数据是按时间组织的,因此我想通过选择每 500 个元素来做到这一点。
我能够加载数据,然后每 500 行选择一次。
我的问题:我可以立即读取每 500 个元素(使用.pd.read_csv() 或其他方法),而不必先读取然后过滤我的数据吗?
问题 2:如果没有对日期列进行排序,您将如何解决这个问题?目前,我假设它是按日期排序的,但所有数据都容易出错。
这是数据的样子(前 5 行)的 sn-p
VendorID tpep_pickup_datetime tpep_dropoff_datetime passenger_count trip_distance RatecodeID store_and_fwd_flag PULocationID DOLocationID payment_type fare_amount extra mta_tax tip_amount tolls_amount improvement_surcharge total_amount
0 1 2017-01-09 11:13:28 2017-01-09 11:25:45 1 3.30 1 N 263 161 1 12.5 0.0 0.5 2.00 0.00 0.3 15.30
1 1 2017-01-09 11:32:27 2017-01-09 11:36:01 1 0.90 1 N 186 234 1 5.0 0.0 0.5 1.45 0.00 0.3 7.25
2 1 2017-01-09 11:38:20 2017-01-09 11:42:05 1 1.10 1 N 164 161 1 5.5 0.0 0.5 1.00 0.00 0.3 7.30
3 1 2017-01-09 11:52:13 2017-01-09 11:57:36 1 1.10 1 N 236 75 1 6.0 0.0 0.5 1.70 0.00 0.3 8.50
4 2 2017-01-01 00:00:00 2017-01-01 00:00:00 1 0.02 2 N 249 234 2 52.0 0.0 0.5 0.00 0.00 0.3 52.80
【问题讨论】:
第一个问题,相信read_csv的skiprows
参数会派上用场
【参考方案1】:
我是否可以立即读取每 500 个元素(使用.pd.read_csv() 或其他方法),而不必先读取然后过滤我的数据?
您可以做的是使用read_csv
中的skiprows
参数,它接受一个类似列表的参数来丢弃感兴趣的行(因此也选择)。所以你可以创建一个长度等于要读取的行数的np.arange
,并使用np.delete
从中删除每个500th
元素,所以这样我们只会每500行读取一次:
n_rows = 9.5e6
skip = np.arange(n_rows)
skip = np.delete(skip, np.arange(0, n_rows, 500))
df = pd.read_csv('my_file.csv', skiprows = skip)
【讨论】:
非常有用。要将记录量减少不到一半,删除步骤可能会发生多次 np.delete() 在我尝试执行代码时产生错误:IndexError: arrays used as indices must be of integer (or boolean) type【参考方案2】:我是否可以立即读取每 500 个元素(使用.pd.read_csv() 或其他方法),而不必先读取然后过滤我的数据?
首先通过自定义函数获取文件的长度,通过numpy.setdiff1d
删除每500行并传递给read_csv
中的skiprows
参数:
#https://***.com/q/845058
def file_len(fname):
with open(fname) as f:
for i, l in enumerate(f):
pass
return i + 1
len_of_file = file_len('test.csv')
print (len_of_file)
skipped = np.setdiff1d(np.arange(len_of_file), np.arange(0,len_of_file,500))
print (skipped)
df = pd.read_csv('test.csv', skiprows=skipped)
如果没有对日期列进行排序,您将如何解决这个问题?目前,我假设它是按日期排序的,但所有数据都容易出错。
思路是通过参数usecols
只读datetime
列,然后对每500个索引值进行排序选择,得到差值再传给参数skiprows
:
def file_len(fname):
with open(fname) as f:
for i, l in enumerate(f):
pass
return i + 1
len_of_file = file_len('test.csv')
df1 = pd.read_csv('test.csv',
usecols=['tpep_pickup_datetime'],
parse_dates=['tpep_pickup_datetime'])
sorted_idx = (df1['tpep_pickup_datetime'].sort_values()
.iloc[np.arange(0,len_of_file,500)].index)
skipped = np.setdiff1d(np.arange(len_of_file), sorted_idx)
print (skipped)
df = pd.read_csv('test.csv', skiprows=skipped).sort_values(by=['tpep_pickup_datetime'])
【讨论】:
以上是关于选择每第 n 行作为 Pandas DataFrame 而无需读取整个文件的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SQL (postgresql) 中选择每第 n 分钟的行