原始数据框是这样的表:
S1_r1_ctrl/ S1_r2_ctrl/ S1_r3_ctrl/
sp|P38646|GRP75_HUMAN 2.960000e-06 5.680000e-06 0.000000e+00
sp|O75694-2|NU155_HUMAN 2.710000e-07 0.000000e+00 2.180000e-07
sp|Q05397-2|FAK1_HUMAN 0.000000e+00 2.380000e-07 7.330000e-06
sp|O60671-2|RAD1_HUMAN NaN NaN NaN
我正在寻找数据框每一列中大于零的最小值。我试图使用此example来回答我的问题。我的代码如下:
df.ne(0).idxmin().to_frame('pos').assign(value=lambda d: df.lookup(d.pos, d.index))
但是我仍然只有零,我的结果看起来像这样:
pos value
S1_r1_ctrl/ sp|Q05397-2|FAK1_HUMAN 0.0
S1_r2_ctrl/ sp|O75694-2|NU155_HUMAN 0.0
S1_r3_ctrl/ sp|P38646|GRP75_HUMAN 0.0
代替此:
pos value
S1_r1_ctrl/ sp|O75694-2|NU155_HUMAN 2.710000e-07
S1_r2_ctrl/ sp|Q05397-2|FAK1_HUMAN 2.380000e-07
S1_r3_ctrl/ sp|O75694-2|NU155_HUMAN 2.180000e-07
我想数据类型可能有问题,但是我不确定。我假设ne(0)
会忽略零,但事实并非如此,所以我很困惑为什么。也许有一种更智能的方式来找到我需要的东西。
答案 0 :(得分:6)
设置
df = pd.DataFrame([[0, 0, 0],
[0, 10, 0],
[4, 0, 0],
[1, 2, 3]],
columns=['first', 'second', 'third'])
使用具有 min(0)
的蒙版:
df[df.gt(0)].min(0)
first 1.0
second 2.0
third 3.0
dtype: float64
@DSM指出,也可以这样写:
df.where(df.gt(0)).min(0)
性能
def chris():
df1[df1.gt(0)].min(0)
def chris2():
df1.where(df1.gt(0)).min(0)
def wen():
a=df1.values.T
a = np.ma.masked_equal(a, 0.0, copy=False)
a.min(1)
def haleemur():
df1.replace(0, np.nan).min()
设置
from timeit import timeit
import matplotlib.pyplot as plt
res = pd.DataFrame(
index=['chris', 'chris2', 'wen', 'haleemur'],
columns=[10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000],
dtype=float
)
for f in res.index:
for c in res.columns:
df1 = df.copy()
df1 = pd.concat([df1]*c)
stmt = '{}()'.format(f)
setp = 'from __main__ import df1, {}'.format(f)
res.at[f, c] = timeit(stmt, setp, number=50)
ax = res.div(res.min()).T.plot(loglog=True)
ax.set_xlabel("N");
ax.set_ylabel("time (relative)");
plt.show()
结果
答案 1 :(得分:5)
也许numpy
是一个很好的选择
a=df.values.T
a = np.ma.masked_equal(a, 0.0, copy=False)
a.min(1)
Out[755]:
masked_array(data=[1, 2, 3],
mask=[False, False, False],
fill_value=999999,
dtype=int64)
答案 2 :(得分:4)
您需要循环遍历所有列,并找到不带0的序列的最小值。
df = pd.DataFrame([[0, 0, 0],
[0, 10, 0],
[4, 0, 0],
[1, 2, 3]],
columns=['first', 'second', 'third'])
[df[col][df[col].ne(0)].min() for col in df.columns]
输出:
[1, 2, 3]
答案 3 :(得分:3)
另一种选择是将0
替换为np.nan
,然后应用min
方法。
注意:这不能解决> 0
的情况,但是测试帧似乎只是非负值。
使用与其他设置相同的设置:
df = pd.DataFrame([[0, 0, 0],
[0, 10, 0],
[4, 0, 0],
[1, 2, 3]],
columns=['first', 'second', 'third'])
df.replace(0, np.nan).min()
first 1.0
second 2.0
third 3.0
dtype: float64
发布此替代方法是因为我发现它比excellent answer的user3483203略快,这也是我对这个问题的第一个直觉
%timeit df.replace(0, np.nan).min()
745 µs ± 2.72 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df[df > 0].min()
1.09 ms ± 14.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
还请注意:
%timeit df[df != 0].min()
1.1 ms ± 16.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
因此,如果在计算聚合时需要忽略特定于的值而不是范围,则replace
与np.nan
似乎是行之有效的方法< / p>
答案 4 :(得分:1)
尝试每列:
df.value.min(skipna=True)