[英]Finding n lowest values for each row in a dataframe
我有一個包含1739行和1455列的大型數據幀。 我想找到每行150個最低值(不是第150個值,而是150個值)。
我用一個基本的for循環遍歷行。
我嘗試了df.min(axis=1)
但它只給出了一分鍾。 而且rolling_min
函數也沒有成功。
是否有任何現有功能,我可以輸入我想找到的值的數量.min?
我的最終目標是取150個最低值並創建斜率然后計算曲線下面積。 對每行執行此操作並添加區域以獲取卷。
數據幀的示例,我有一個看起來像這樣的df:
-218.7 -218.4 ... 217.2 217.5
0 56.632706 13.638315 ... 76.543000 76.543000
1 56.633455 13.576762 ... 76.543000 76.543000
2 -18.432203 -18.384091 ... 76.543000 76.543000
3 -18.476594 -18.439804 ... 76.543000 76.543000
標題是'-218.7 ...',它是掃描的x軸中的坐標。 數據是y軸掃描的高度。 我需要的是每行150個最低值以及相關的列標題,因為我想為每一行制作一條曲線然后計算曲線下面積。
所以我需要為每一行這樣的東西:
-218.7 -218.4 ... for 150 columns
4 -18.532035 -18.497517 ... for 150 values
我不認為我需要存儲每行的標題信息,for循環將逐個通過每一行。
使用.argsort
來獲取基礎數組的索引。 切片值和列索引以獲取所需的所有信息。 我們將創建一個MultiIndex,以便我們可以將列標題和值存儲在同一個DataFrame中。 第一級將是您的原始索引。
import pandas as pd
import numpy as np
np.random.seed(1)
df = pd.DataFrame(np.random.randint(1,100000, (1739, 26)))
df.columns = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
N = 7 # 150 in your case
idx = np.argsort(df.values, 1)[:, 0:N]
pd.concat([pd.DataFrame(df.values.take(idx), index=df.index),
pd.DataFrame(df.columns[idx], index=df.index)],
keys=['Value', 'Columns']).sort_index(level=1)
0 1 2 3 4 5 6
Columns 0 C K U V I G P
Value 0 5193 7752 8445 19947 20610 21441 21759
Columns 1 R J W C B D G
Value 1 432 3607 16278 17138 19434 26104 33879
Columns 2 K S E F M O U
Value 2 16 1047 1845 9553 12314 13784 19432
Columns 3 K Q A S X W G
Value 3 244 5272 10836 13682 29237 33230 34448
Columns 4 K T L U C D M
Value 4 9765 11275 13160 22808 30870 33484 42760
...
Columns 1736 I L U W B X N
Value 1736 7099 7922 11047 12613 15502 18409 21576
Columns 1737 J K E V O M S
Value 1737 3000 5538 7933 13777 17310 22640 24750
Columns 1738 O U A X E I F
Value 1738 5118 5775 10267 11320 17659 30055 30702
如果我理解正確,問題歸結為在M(> k)數字列表中獲得k個最小數字。 然后將其單獨應用於每一行。
如果numpy可用且順序無關緊要,你可以嘗試使用argpartition :給定參數k,它以假定第k個元素被放入其排序位置的方式對數組進行分區,所有較小的數字都在之前,所有較大的數字都在后面(以未指定的順序):
import numpy as np
row = np.array([1, 6, 2, 12, 7, 8, 9, 11, 15, 26])
k = 5
idx = np.argpartition(row, k)[:k]
print(idx)
print(row[idx])
-->
[1 0 2 4 5]
[6 1 2 7 8]
編輯 :這也適用於完整數組的行/明智:
import numpy as np
data = np.array([
[1, 6, 2, 12, 7, 8, 9, 11, 15, 26],
[1, 65, 2, 12, 7, 8, 9, 11, 15, 26],
[16, 6, 2, 12, 7, 8, 9, 11, 15, 26]])
k = 5
idx = np.argpartition(data, k)[:,:k]
print(idx)
-->
[[1 0 2 4 5]
[2 0 4 5 6]
[4 2 1 5 6]]
您可以使用heapq.nsmallest
查找列表中的n
最小數字。 這可以使用.apply
快速應用於數據幀的每一行:
import pandas as pd
import numpy as np
import heapq
df = pd.DataFrame(np.random.randn(1000, 1000))
# Find the 150 smallest values in each row
smallest = df.apply(lambda x: heapq.nsmallest(150, x), axis=1)
每行最小值現在是df
相應行中150個最小值的列表。
可以使用以下方法將其轉換為數據框:
smallest_df = pd.DataFrame(smallest.values.tolist())
現在這是一個數據框,其中每一行對應於原始數據框中的每一行。 有150列,原始的每一行中有150個最小值。
smallest_df.head()
我不知道如何在不循環遍歷行的情況下執行此操作:
df = df.transpose()
for col in df.columns:
min_values = df[col].sort_values()[0:150]
# now calc slope/area
如果你使用for循環迭代df,就像你在問題中提到的那樣,你可以簡單地這樣做:
for index, row in df.iterrows(): # your loop
new_row = sorted(row.values)[:150]
# new_row should be a list with length 150.
測試:
import numpy
import pandas
import random
# generate dummy data
l = list(range(1600))
random.shuffle(l)
a = numpy.array(l)
a = a.reshape(40, 40) # columns x rows
dummy_df = pandas.DataFrame(a)
# dummy_df.shape = (40, 40)
smallest = []
for idx, row in dummy_df.iterrows():
smallest.append(sorted(row.values)[:10])
new_df = pandas.DataFrame(numpy.array(smallest))
# new_df.shape = (40, 10)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.