我被下面的事情困住了:
我试图从pandas
数据框中获取值,修改它们,然后放入新的dataframe
/np.array
。
数据框df1
看起来像这样:
1. 0 0 ... 0.5 0.5 .. 0
2. 0 0 ... 0 1 .. 0
3. 0.5 0 ... 0 0.5 .. 0
...
。我有很多零元素,除了一些非零元素之和为1。
我想做的是取每一行(向量),用uniform
分布在一些低值和非零项之间的最小值之间的值修改零项,然后将结果附加到一个新的数据帧或numpy数组中。
df2
的结果应该是这样的:
1. 0.22 0.15 ... 0.5 0.5 .. 0.004
2. 0.7 0.654 ... 0.0567 1 .. 0.45
3. 0.5 0.432 ... 0.354 0.5 .. 0.0432
...
我正在尝试使用以下代码:
arr = np.array([[]])
for j in range(len(df1)):
for i in range(103): #103 is the length of these vectors
if df1.iloc[j][i] == 0:
arr=np.append([np.random.uniform(low=0.01, high=df1.iloc[j][3:].min()), arr])
else:
arr[j][i]= df1.iloc[j][i]
我得到的是以下错误:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-256-141abfd58de1> in <module>
3 for j in range(len(data)):
4 for i in range(103):
----> 5 if data.iloc[j][i] == 0:
6 arr=np.append([np.random.uniform(low=0.01, high=data.iloc[j][3:].min()), arr])
7 else:
~anaconda3libsite-packagespymatgencorecomposition.py in __eq__(self, other)
167 # in the elmap, so checking len enables us to only check one
168 # compositions elements
--> 169 if len(self) != len(other):
170 return False
171 for el, v in self.items():
TypeError: object of type 'int' has no len()
许多谢谢,
詹姆斯
首先,让我们创建一个包含10行103列的df1
,其中大部分为零,所有行的总和为1:
>>> df1 = pd.DataFrame({r: {val: np.random.randint(20) for val in np.random.choice(np.arange(103), np.random.randint(2, 5))} for r in range(10)}).T
>>> df1 = df1.div(df1.sum(axis='columns'), axis='index').reindex(columns=np.arange(103)).fillna(0)
让我们通过查看数据、对行求和和每行计数0来检查我们做了什么:
>>> df1
0 1 2 3 4 5 ... 97 98 99 100 101 102
0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.000
1 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.000
2 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.000
3 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.000
4 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.000
5 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.1 0.0 0.0 0.0 0.0 0.475
6 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.000
7 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.000
8 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.000
9 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.000
[10 rows x 103 columns]
>>> df1.sum(axis='columns')
0 1.0
1 1.0
2 1.0
3 1.0
4 1.0
5 1.0
6 1.0
7 1.0
8 1.0
9 1.0
dtype: float64
>>> df1.ne(0).sum(axis='columns').astype(int)
0 3
1 2
2 3
3 2
4 3
5 4
6 4
7 3
8 3
9 3
dtype: int64
看来这符合你对df1
的规格,现在我们可以开始工作了。
首先,让我们屏蔽所有的零,这样我们就有一个数据帧来提取最小非零值:
>>> df1_nz = df1.mask(df1.eq(0))
>>> df1_nz.min(axis='columns')
0 0.282051
1 0.210526
2 0.181818
3 0.464286
4 0.272727
5 0.100000
6 0.068182
7 0.185185
8 0.050000
9 0.222222
dtype: float64
现在我们可以每行调用一次np.uniform
来获得一个充满随机值的数据帧,并使用这些随机值来填充非零的df1:
>>> random_vals = pd.DataFrame({
... r: np.random.uniform(0.01, n, 103) for r, n in df1_nz.min(axis='columns').iteritems()
... }, index=df1.columns).T
>>> df2 = df1_nz.fillna(random_vals)
>>> df2
0 1 2 3 ... 99 100 101 102
0 0.274312 0.119229 0.200223 0.126925 ... 0.250511 0.076387 0.262691 0.091327
1 0.178858 0.032533 0.171083 0.187775 ... 0.104859 0.141225 0.145604 0.024747
2 0.149279 0.095146 0.067775 0.074993 ... 0.167393 0.109034 0.082226 0.146610
3 0.101093 0.391821 0.266622 0.336723 ... 0.126007 0.438758 0.321557 0.339710
4 0.037873 0.250409 0.123596 0.152685 ... 0.086009 0.190996 0.086574 0.253784
5 0.051473 0.032933 0.085726 0.064984 ... 0.064354 0.050978 0.086429 0.475000
6 0.043807 0.021605 0.049259 0.060036 ... 0.043379 0.052804 0.039904 0.044067
7 0.033173 0.030694 0.178263 0.042904 ... 0.183436 0.019724 0.024167 0.074844
8 0.019714 0.019226 0.028672 0.046260 ... 0.023111 0.042002 0.028637 0.018817
9 0.137686 0.101749 0.127393 0.026675 ... 0.083874 0.197242 0.170042 0.143624
[10 rows x 103 columns]
如果我们在df1非零的位置上过滤df2,我们可以看到它仍然是相同的值:
>>> df2.where(df1.ne(0)).stack()
0 56 0.410256
58 0.307692
77 0.282051
1 13 0.210526
77 0.789474
2 25 0.181818
51 0.636364
92 0.181818
3 19 0.535714
74 0.464286
4 18 0.454545
33 0.272727
91 0.272727
5 38 0.200000
54 0.225000
97 0.100000
102 0.475000
6 7 0.409091
12 0.068182
30 0.250000
73 0.272727
7 18 0.518519
57 0.185185
69 0.296296
8 7 0.050000
40 0.250000
90 0.700000
9 20 0.259259
38 0.518519
89 0.222222
dtype: float64
您没有解释[3:]
,所以我将忽略它,但您可以在此方法中使用df1_nz = df1.mask(…)[df1.columns[3:]]
重新引入它。