(Python,DataFrame):添加一个列并在行中插入第n个最小值

时间:2017-09-18 17:20:49

标签: python pandas dataframe

如何在DataFrame中连续找到第n个最小数字,并将该值作为新列中的条目添加(因为我最终想要导出数据)。 Example Data

enter image description here

4 个答案:

答案 0 :(得分:4)

设置

np.random.seed([3,14159])

df = pd.DataFrame(np.random.randint(10, size=(4, 5)), columns=list('ABCDE'))

   A  B  C  D  E
0  4  8  1  1  9
1  2  8  1  4  2
2  8  2  8  4  9
3  4  3  4  1  5

在以下所有解决方案中,我假设n = 3

解决方案1 ​​
功能prt低于
使用np.partition将最小的部分放在分区的左侧,将最大的部分放在右侧。然后全部向左走,找到最大值

df.assign(nth=np.partition(df.values, 3, axis=1)[:, :3].max(1))

   A  B  C  D  E  nth
0  4  8  1  1  9    4
1  2  8  1  4  2    2
2  8  2  8  4  9    8
3  4  3  4  1  5    4

解决方案2
功能srt低于
np.sort

更直观但成本更高的时间复杂度
df.assign(nth=np.sort(df.values, axis=1)[:, 2])

   A  B  C  D  E  nth
0  4  8  1  1  9    4
1  2  8  1  4  2    2
2  8  2  8  4  9    8
3  4  3  4  1  5    4

解决方案3
功能rnk低于
使用pd.DataFrame.rank
简化为浮动的简洁版

df.assign(nth=df.where(df.rank(1, method='first').eq(3)).stack().values)

   A  B  C  D  E  nth
0  4  8  1  1  9  4.0
1  2  8  1  4  2  2.0
2  8  2  8  4  9  8.0
3  4  3  4  1  5  4.0

解决方案4
功能whr低于
使用np.wherepd.DataFrame.rank

i, j = np.where(df.rank(1, method='first') == 3)
df.assign(nth=df.values[i, j])

   A  B  C  D  E  nth
0  4  8  1  1  9    4
1  2  8  1  4  2    2
2  8  2  8  4  9    8
3  4  3  4  1  5    4

<强>时序
请注意,srt最快但与prt相当,但对于较大数量的列,prt的效率更高效。

res.plot(loglog=True)

enter image description here

prt = lambda df, n: df.assign(nth=np.partition(df.values, n, axis=1)[:, :n].max(1))
srt = lambda df, n: df.assign(nth=np.sort(df.values, axis=1)[:, n - 1])
rnk = lambda df, n: df.assign(nth=df.where(df.rank(1, method='first').eq(n)).stack().values)
def whr(df, n):
    i, j = np.where(df.rank(1, method='first').values == n)
    return df.assign(nth=df.values[i, j])

res = pd.DataFrame(
    index=[10, 30, 100, 300, 1000, 3000, 10000],
    columns='prt srt rnk whr'.split(),
    dtype=float
)

for i in res.index:
    num_rows = int(np.log(i))
    d = pd.DataFrame(np.random.rand(num_rows, i))
    for j in res.columns:
        stmt = '{}(d, 3)'.format(j)
        setp = 'from __main__ import d, {}'.format(j)
        res.at[i, j] = timeit(stmt, setp, number=100)

答案 1 :(得分:1)

以下是查找列表中第n个最小项目的方法:

def find_nth_in_list(list, n):
    return sorted(list)[n-1]

用法:

list =[10,5,7,9,8,4,6,2,1,3]
print(find_nth_in_list(list, 2))

输出:

2

您可以将行项目作为列表提供给此功能。

修改

您可以找到具有此功能的行:

#Returns all rows as a list
def find_rows(df):         
    rows=[]
    for row in df.iterrows():
        index, data = row
        rows.append(data.tolist())
    return rows

使用示例:

rows = find_rows(df)                           #all rows as a list
smallest_3th = find_nth_in_list(rows[2], 3)    #3rd row, 3rd smallest item

答案 2 :(得分:1)

您可以按照以下方式执行此操作:

df.assign(nth=df.apply(lambda x: np.partition(x, nth)[nth], axis='columns'))

示例:

In[72]: df = pd.DataFrame(np.random.rand(3, 3), index=list('abc'), columns=[1, 2, 3])
In[73]: df
Out[73]: 
          1         2         3
a  0.436730  0.653242  0.843014
b  0.643496  0.854859  0.531652
c  0.831672  0.575336  0.517944

In[74]: df.assign(nth=df.apply(lambda x: np.partition(x, 1)[1], axis='columns'))
Out[74]: 
          1         2         3       nth
a  0.436730  0.653242  0.843014  0.653242
b  0.643496  0.854859  0.531652  0.643496
c  0.831672  0.575336  0.517944  0.575336

答案 3 :(得分:0)

生成一些随机数据

dd=pd.DataFrame(data=np.random.rand(7,3))

使用numpy找到每行的最小值

dd['minPerRow']=dd.apply(np.min,axis=1)

导出结果

dd['minPerRow'].to_csv('file.csv')