Python 如何获取数据帧列中数字周围的值?
假设以下示例数据帧:Python 如何获取数据帧列中数字周围的值?,python,pandas,dataframe,Python,Pandas,Dataframe,假设以下示例数据帧: df = pd.DataFrame([10,15,9,3,5,6,7,12,9], columns = ['numbers']).sort_values(by = 'numbers') 对于numbers列中的每个值,我希望获取该值及其周围的4数字。因此,只要可能,我希望比当前值小2个,大2个。当不可能时,我希望获取小于该值的k数字和大于该值的n数字,以便k+n=4 循环我的示例,第一个值是3。没有小于3的数字,因此输出为大于3的4个数字: 3,5,6,7,9 期望输出
df = pd.DataFrame([10,15,9,3,5,6,7,12,9], columns = ['numbers']).sort_values(by = 'numbers')
对于numbers列中的每个值,我希望获取该值及其周围的4数字。因此,只要可能,我希望比当前值小2个,大2个。当不可能时,我希望获取小于该值的k数字和大于该值的n数字,以便
k+n=4
循环我的示例,第一个值是3。没有小于3的数字,因此输出为大于3的4个数字:3,5,6,7,9 期望输出: 输出列具有所需的输出,对应于数字列中的每个输入。(我使用引号突出显示当前值)
看看
pd.rolling()
或pd.Series.shift()
。然后将第一个和最后一个n作为特例:
df.loc[[0:4],['n1','n2','n3','n4']] = df['numbers'][:4].values
我建议将每个新值设置为一列,而不是将其全部打包为一列,因为这样更容易使用。如果你愿意的话,你可以把它们浓缩成str。我想不出一个聪明的方法来做这件事,但我认为这是可行的:
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)
这在一般情况下也适用。在某些情况下,它可能会断裂,需要稍微调整。也许有一种更聪明的方法可以想出更好的解决方案;想不出一个聪明的办法
让我知道它是否有效
谢谢 如果你想为自己的学习体验编写程序,一个非常简单的方法是
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]
,因为0
位于1
之前
现在,如果您想将其应用于您的pandas数据帧,那么将reset\u index(drop=True)
添加到行尾以重置索引
然后
如输出所示,对于第一行值3
,没有过去的值,因此函数返回空列表,但也返回[5,6]
,因为这些是未来的值。然后对于下一行,5
,函数返回[0]
作为过去值,返回[6,7]
作为未来值。然后等等
然后,您可以修改它以适合您的目的。当然,这只是一个例子,绝不意味着它是“最终的”。设置
df = pd.DataFrame([10,15,9,3,5,6,7,12,9], columns = ['numbers']).sort_values(by = 'numbers')
解决方案
#reset index so it's sorted
df.reset_index(inplace=True)
#build reference index lists
start = [0,1]+[2]*(len(df)-4)+[3,4]
end = start[::-1]
#Extract elements based on the start and end reference index.
df['output'] = df.apply(lambda x: sum([df.iloc[x.name-start[x.name]:x.name]['numbers'].tolist(),
[x['numbers']],df.iloc[x.name+1:x.name+end[x.name]+1]['numbers'].tolist()],[]), axis=1)
df
Out[610]:
index numbers output
0 3 3 [3, 5, 6, 7, 9]
1 4 5 [3, 5, 6, 7, 9]
2 5 6 [3, 5, 6, 7, 9]
3 6 7 [5, 6, 7, 9, 9]
4 2 9 [6, 7, 9, 9, 10]
5 8 9 [7, 9, 9, 10, 12]
6 0 10 [9, 9, 10, 12, 15]
7 7 12 [9, 9, 10, 12, 15]
8 1 15 [9, 9, 10, 12, 15]
'numbers'
列中的值是否唯一?如果不是,预期的输出是什么?它们不是唯一的。数字可以重复,就像我上面的例子一样。数字9重复。它不影响输出。输出列是什么?输出列的每一行都有一个数字列表?输出列是我想要的输出,对应于数字列中的每个输入。
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], [])
df = pd.DataFrame([10,15,9,3,5,6,7,12,9], columns = ['numbers']).sort_values(by = 'numbers')
#reset index so it's sorted
df.reset_index(inplace=True)
#build reference index lists
start = [0,1]+[2]*(len(df)-4)+[3,4]
end = start[::-1]
#Extract elements based on the start and end reference index.
df['output'] = df.apply(lambda x: sum([df.iloc[x.name-start[x.name]:x.name]['numbers'].tolist(),
[x['numbers']],df.iloc[x.name+1:x.name+end[x.name]+1]['numbers'].tolist()],[]), axis=1)
df
Out[610]:
index numbers output
0 3 3 [3, 5, 6, 7, 9]
1 4 5 [3, 5, 6, 7, 9]
2 5 6 [3, 5, 6, 7, 9]
3 6 7 [5, 6, 7, 9, 9]
4 2 9 [6, 7, 9, 9, 10]
5 8 9 [7, 9, 9, 10, 12]
6 0 10 [9, 9, 10, 12, 15]
7 7 12 [9, 9, 10, 12, 15]
8 1 15 [9, 9, 10, 12, 15]