假设以下示例DataFrame:
df = pd.DataFrame([10,15,9,3,5,6,7,12,9], columns = ['numbers']).sort_values(by = 'numbers')
print df
numbers
3 3
4 5
5 6
6 7
2 9
8 9
0 10
7 12
1 15
对于数字列中的每个值,我想要获取该值以及围绕它的 4 数字。这样,只要有可能,我想要比当前值小2个数字和2个数字。如果不可能,我想获取小于值的 k 数字和大于该值的 n 数字,例如k + n = 4
。
循环显示我的示例,第一个值是 3 。没有小于 3 的数字,因此输出为大于 3 的4个数字:
3 下,5,6,7,9
期望的输出: 输出列具有所需的输出,对应于数字列中的每个输入。 (我使用引号突出显示当前值)
numbers Output
3 3 '3' ,5,6,7,9
4 5 3, '5' ,6,7,9
5 6 3,5, '6' ,7,9
6 7 5,6, '7' ,9,9
2 9 6,7, '9' ,9,10
8 9 .
0 10 .
7 12 .
1 15 9,9,10,12, '15'
答案 0 :(得分:1)
<强>设置强>
0 to N
<强>解决方案强>
N+1
答案 1 :(得分:0)
查看pd.rolling()
或pd.Series.shift()
。然后只需将第一个和最后一个n作为一个特例:
df.loc[[0:4],['n1','n2','n3','n4']] = df['numbers'][:4].values
我建议将每个新值都设为一列,而不是将其全部打包到一个列中,因为它更容易使用这种方式。如果你愿意,你可以将它们连接到str。
答案 2 :(得分:0)
我无法想出一个聪明的人,但我觉得这很有效:
df2 =df.copy()
for i in range(-4, 5, 1):
df2['{}_shifted'.format(str(i))] = df.numbers.shift(i) #Here I'm making new columns to represent the shifted numbers
df2 =df2.drop('0_shifted', axis =1) #dropping the 0_shifted column because it's the same as the `numbers` column
接下来我们要处理特殊情况,即前两行和后两行
nums = []
for i,j,in enumerate( df2.iterrows()):
if np.isnan((j[1][-2])):
nums.append(list(j[1])[i+1:i+5])
elif np.isnan((j[1][2])):
nums.append((list(j[1])[i-3:i+1]))
else:
nums.append(list(j[1])[len(list(j[1]))//2 -1:len(list(j[1]))//2 +3 ])
上面的代码将返回一个列表nums
,我们将把它列入一个系列并连接到原始数据框
close_numbers =pd.Series(nums, index = df.index)
pd.concat((df, close_numbers), axis =1)
这也适用于一般情况。在某些情况下可能会中断,需要稍微调整一下。可能有更聪明的方法来提出更好的解决方案;无法找到一个聪明的方法。
让我知道它是否有效。
感谢。
答案 3 :(得分:0)
如果你想自己编写一个这样的学习经历,一个非常简单的方法是通过
def rollingWindow(x, size=2):
n = len(x)
results = []
for i in range(n):
temp = (x[i], x[:i][-size:], x[i:][1:(size+1)])
results.append(temp)
print(temp) ## only for show
return results
如果您要传递一个简单的数字0到9的列表,那么
>>> rollingWindow(range(10))
(0, [], [1, 2])
(1, [0], [2, 3])
(2, [0, 1], [3, 4])
(3, [1, 2], [4, 5])
(4, [2, 3], [5, 6])
(5, [3, 4], [6, 7])
(6, [4, 5], [7, 8])
(7, [5, 6], [8, 9])
(8, [6, 7], [9])
(9, [7, 8], [])
正如您所看到的,对于第一行,只返回一个空列表,因为0之前没有任何内容。然后,对于下一行(1
),返回[0]
,因为{{ 1}}位于0
之前。
现在,如果您想将此应用到您的pandas数据框中,请将1
添加到行的末尾以重置索引。
然后
reset_index(drop=True)
如输出所示,对于第一行值df = pd.DataFrame([10,15,9,3,5,6,7,12,9], columns = ['numbers']).sort_values(by = 'numbers').reset_index(drop=True)
df.apply(rollingWindow, axis = 0)
Out[5]:
numbers
0 (3, [], [5, 6])
1 (5, [3], [6, 7])
2 (6, [3, 5], [7, 9])
3 (7, [5, 6], [9, 9])
4 (9, [6, 7], [9, 10])
5 (9, [7, 9], [10, 12])
6 (10, [9, 9], [12, 15])
7 (12, [9, 10], [15])
8 (15, [10, 12], [])
,没有过去的值,因此函数返回空列表,但也返回3
,因为这些是未来值。然后,对于下一行[5,6]
,函数返回5
作为过去值,[0]
作为未来值。等等。
然后您可以修改它以适合您的目的。这只是一个例子,当然,绝不是最终&#34;最终&#34;。