tl; dr:我的代码执行我想要的除了一个元素:为每个代码块定义 tick_slice
的行不返回所需的切片 . 如果您想跳过我的数据的详细信息,请跳到下面以"My Question:"开头的第4段 .
我有下面的代码,其中我将csv文件读入数据帧 . csv文件中的数据组织如下:第一行包含格式为YYYYMMDD的日期,它们在~350列中具有降序值 . 在每列(每个日期下面)都是唯一标识符(有点像股票代码) . 大多数列具有不同的行数,范围从几百到几千,标识符从“最佳”到“最差”排序 .
我的愿望是创建一个矩阵(然后将其输出到一个新的csv文件) . 矩阵构建如下:从输入csv数据的第一列开始,获取标识符的最高十分位数(10%)并将它们放在输出矩阵的第一列中 . 接下来,移动到输入csv数据的第二列,从此列获取标识符的最高十分位数,并将这些标识符放在输出矩阵的第一列下面,从第一步放置到那里 . 对变量 hld_per
给出的次数重复此操作 . 然后移到右边一列并重复这些步骤 . 所以在我当前的代码中,嵌套的for循环首先会覆盖输入csv数据的1:12列,然后是第2:13列等 .
我目前有十个这段代码重复,以创建10个输出文件,每个十分位一个,最好到最差(下面的代码只显示前两个十块,以节省空间;另外,我知道重复这个块10次是低效的,但是我会在我按照需要运行当前代码后解决这个问题 .
我的问题:下面的代码完成了我想要的大部分内容,但为每个嵌套for循环定义 tick_slice
的行不知道如何应用它 .
任何帮助是极大的赞赏 . 此外,如果在熊猫中有一种完全不同的方式,我肯定会接受任何建议 .
部分代码:
import pandas as pd
hld_per = 12
quantiles = 10
permnos = pd.read_csv('Ranks.csv')
my_headers = list(permnos.columns)
total_cols = len(permnos.columns)
ports1 = []
for i in range(total_cols-(hld_per-1)):
permlist = []
for j in range(hld_per):
tick_slice = int(permnos.iloc[:,i+j].count()/quantiles)
col_slice = permnos.iloc[0:tick_slice, i+j].tolist()
permlist = permlist + col_slice
ports1.append(permlist)
matrix = pd.DataFrame(ports1)
matrix = matrix.T
matrix.columns = my_headers[0:len(matrix.columns)]
matrix.to_csv('ports1.csv', sep=',', index=False, header=True)
ports2 = []
for i in range(total_cols-(hld_per-1)):
permlist = []
for j in range(hld_per):
tick_slice = int(permnos.iloc[:,i+j].count()/quantiles)
col_slice = permnos.iloc[tick_slice:tick_slice*2, i+j].tolist()
permlist = permlist + col_slice
ports2.append(permlist)
matrix = pd.DataFrame(ports2)
matrix = matrix.T
matrix.columns = my_headers[0:len(matrix.columns)]
matrix.to_csv('ports2.csv', sep=',', index=False, header=True)
从这段代码中, permnos.head()
产生:
20131231 20131130 20131031 20130930 20130831 20130731 20130630 \
0 93044.0 93044.0 13264 13264 89169.0 82486.0 91274.0
1 79702.0 91515.0 90710 81148 47387.0 88359.0 93353.0
2 85751.0 85724.0 88810 11513 85576.0 47387.0 85576.0
3 85576.0 89169.0 81562 81562 81148.0 10294.0 10294.0
4 13264.0 90710.0 82281 47387 11285.0 90710.0 47387.0
matrix.head()
for ports1
yield:
20131231 20131130 20131031 20130930 20130831 20130731 20130630 \
0 93044.0 93044.0 13264.0 13264.0 89169.0 82486.0 91274.0
1 79702.0 91515.0 90710.0 81148.0 47387.0 88359.0 93353.0
2 85751.0 85724.0 88810.0 11513.0 85576.0 47387.0 85576.0
3 93044.0 13264.0 13264.0 89169.0 82486.0 91274.0 85653.0
4 91515.0 90710.0 81148.0 47387.0 88359.0 93353.0 91274.0
matrix.head()
for ports2
yield:
20131231 20131130 20131031 20130930 20130831 20130731 20130630 \
0 85576.0 89169.0 81562.0 81562.0 81148.0 10294.0 10294.0
1 13264.0 90710.0 82281.0 47387.0 11285.0 90710.0 47387.0
2 90539.0 47387.0 93044.0 92805.0 82281.0 89169.0 66852.0
3 89169.0 81562.0 81562.0 81148.0 10294.0 10294.0 89169.0
4 90710.0 82281.0 47387.0 11285.0 90710.0 47387.0 93353.0
2 回答
如果我理解正确,那么是的,
qcut()
可以为你找到你正在寻找的分裂 .我们将从构建示例
permnos
数据框开始 . 这基于OPpermnos.head()
,加上一些额外的行来说明列长度的异质性 .考虑一下
qcut()
returns:我们正在传递系列数据,因此我们将获得一系列类型
category
作为输出 . 例如:我们可以看到它如何处理我们的不均匀分裂;这三个类别分别制作了2个,1个和2个数据点的桶 . 现在,我们可以构造一个布尔掩码,只获取我们关心的存储桶中的条目:
通过这种方法,我们应该能够通过仅获取在每次迭代中在目标分位数中被分块的条目来从每列中获取我们想要的切片 .
我们可以通过将核心操作包装在一个函数_390250中来压缩一些东西 .
UDPATED
(针对多个矩阵推广,每条评论)
鉴于我们可能想要基于
n_bin
构建任意数量的矩阵,我们设置了一个construct_matrix()
循环,其中第一个start_pos
之后的每个新start_pos
都是start_pos
end_pos
,在上一次迭代的函数内设置 . 我们将生成的矩阵存储在一个列表中,matrices
.输出:
这应该可以获得您在列和分位数之间寻找的(大致)偶数分割 .
我从来没有能够使用
qcut
为此制作解决方案,但我已经提出了一个符合我的规格的替代解决方案 . 希望其他人也会发现这个用途 .