首页 > 解决方案 > 从 pandas 数据框中获取值,修改它们并将它们附加到新的 dataframe/np.array

问题描述

我有点坚持以下事情:

我正在尝试从数据框中获取值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
...

即我有很多零条目,除了一些总和为一的非零条目。

我想要做的是每行(向量),用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:

~\anaconda3\lib\site-packages\pymatgen\core\composition.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()

非常感谢,

詹姆士

标签: pandasnumpy

解决方案


首先,让我们创建一个df1 有 10 行和 103 列的大多数为零且所有行总和为 1 的 a:

>>> 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)

让我们通过查看数据、汇总行和每行计数零来检查我们做了什么:

>>> 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

现在从那里 min 我们可以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:]]


推荐阅读