gpt4 book ai didi

python - pandas loc 函数在写入和读取时引用不同的行 -> ValueError

转载 作者:太空宇宙 更新时间:2023-11-04 02:13:15 25 4
gpt4 key购买 nike

当运行下面的示例代码时,我得到一个

ValueError: cannot set using a multi-index selection indexer with a different
length than the value

执行时出现错误

df.loc[(9, 0), ("clouds", "type")] = np.array([None, None])

这里:

~\Anaconda3\lib\site-packages\pandas\core\indexing.py in _setitem_with_indexer(self, indexer, value)
492
493 if len(obj[idx]) != len(value):
--> 494 raise ValueError

问题似乎与将 numpy 数组写入数据框的“单元格”有关。似乎 obj[idx] 指的是数据帧中的索引 (20,),而它应该指的是 (9,0)。执行时引发错误的迭代之前的几次迭代

df.loc[(6, 0), ("clouds", "type")] = np.array([None, None])

没有错误是巧合 obj[idx] 引用数据帧中的索引 (17,),它有 2 个子索引,因此偶然 len(obj[idx ])==len(值)==2.

备注:

读书的时候

df.loc[(9, 0), ("clouds", "type")].values

它正确返回 [104]

问题:

我是否错误地使用了 .loc 函数?我做错了什么吗?或者这是 Pandas 内部的问题?我该如何避免呢?

我非常感谢任何帮助,因为这个问题让我卡住了几天:/

代码:

import pandas as pd
import numpy as np

mi = pd.MultiIndex(levels=[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]],
labels=[[0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 12, 13, 14, 14,
14, 15, 16, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22],
[0, 1, 0, 1, 2, 3, 0, 1, 2, 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 2, 0, 0,
0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 0, 1, 2, 0, 1, 2]])


mc = pd.MultiIndex(levels=[['clouds', 'group', 'header', 'vertical_visibility', 'visibility', 'weather', 'wind', 'windshear'],
['', 'BR', 'DS', 'DU', 'DZ', 'FC', 'FG', 'FU', 'GR', 'GS', 'HZ', 'IC', 'PL', 'PO', 'PY', 'RA', 'SA', 'SG', 'SN', 'SQ', 'SS', 'UP', 'VA', 'altitude', 'ceiling', 'direction', 'form', 'from_date', 'from_hours', 'from_minutes', 'gust', 'icao_code', 'layer', 'more', 'origin_date', 'origin_hours', 'origin_minutes', 'probability', 'range', 'speed', 'till_date', 'till_hours', 'till_minutes', 'type', 'unit', 'valid_from_date', 'valid_from_hours', 'valid_till_date', 'valid_till_hours'],
['bool', 'intensity', 'modifier']],
labels=[[0, 0, 0, 1, 1, 1],
[24, 32, 43, 27, 28, 29],
[-1, -1, -1, -1, -1, -1]])

arr = np.array(range(0,len(mi)*len(mc))).reshape(len(mi),len(mc))

df = pd.DataFrame(arr, index=mi, columns=mc)


values = {0: {0: [None]}, 1: {0: [None], 1: [None], 2: [None], 3: [None]}, 2: {0: [None], 2: [None]}, 3: {0: [None], 1: [None], 2: [None], 3: [None], 4: [None], 5: [None]}, 4: {0: [None]}, 6: {0: [None, None]}, 9: {0: [None, None]}}


for i, val in values.items():
for j, v in val.items():
df.loc[(i,j),("clouds", "type")] = np.array(v)

最佳答案

("clouds", "type", None) 列有整数数据类型:

In [28]: df[("clouds", "type", None)].dtype
Out[28]: dtype('int64')

因此,如果要将 NumPy 数组分配给此列,首先将 dtype 更改为 object:

df[("clouds", "type", None)] = df[("clouds", "type", None)].astype('object')

  • 使用df.atdf.iat 选择或分配值给 DataFrame 的特定单元格
  • 使用 df.locdf.iloc 选择或分配值给列、行或子数据帧。

因此,在这里使用df.at:

df[("clouds", "type", None)] = df[("clouds", "type", None)].astype('object')
for i, val in values.items():
for j, v in val.items():
df.at[(i, j), ("clouds", "type", None)] = np.array(v)

它产生一个看起来像的df

      clouds                         group                        
ceiling layer type from_date from_hours from_minutes
NaN NaN NaN NaN NaN NaN
0 0 0 1 [None] 3 4 5
1 6 7 8 9 10 11
1 0 12 13 [None] 15 16 17
1 18 19 [None] 21 22 23
2 24 25 [None] 27 28 29
3 30 31 [None] 33 34 35
2 0 36 37 [None] 39 40 41
1 42 43 44 45 46 47
2 48 49 [None] 51 52 53
3 0 54 55 [None] 57 58 59
1 60 61 [None] 63 64 65
2 66 67 [None] 69 70 71
3 72 73 [None] 75 76 77
4 78 79 [None] 81 82 83
5 84 85 [None] 87 88 89
4 0 90 91 [None] 93 94 95
5 0 96 97 98 99 100 101
6 0 102 103 [None, None] 105 106 107
7 0 108 109 110 111 112 113
8 0 114 115 116 117 118 119
9 0 120 121 [None, None] 123 124 125
...

关于 the comment您希望将云/类型列用于分类数据:

具有分类数据的列必须包含可散列 值。通常,使可变对象可散列是没有意义的。因此,例如,Python 可变内置函数(例如列表)或 NumPy 数组是不可哈希的。但是 Python 不可变内置函数(例如元组)是可哈希的。因此,如果您使用

df.at[(i, j), ("clouds", "type", None)] = tuple(v)

然后你可以制作 category dtype 的 ("clouds", "type", None) 列:

df[("clouds", "type", None)] = df[("clouds", "type", None)].astype('object')
for i, val in values.items():
for j, v in val.items():
df.at[(i, j), ("clouds", "type", None)] = tuple(v)

df[("clouds", "type", None)] = df[("clouds", "type", None)].astype('category')

注意需要先把object的列做成dtype,这样可能会包含元组等Python对象,毕竟只有转换成category dtype可能的值已分配。


根据您要对数据执行的操作,"tidy" the data 也可能更有意义通过仅将字符串分配给 clouds/type 列并使用多行而不是元组:

例如,

6  0     102   103  'foo'       105        106          107
6 0 102 103 'bar' 105 106 107

代替

6  0     102   103  ('foo', 'bar')       105        106          107

使用多行的一个优点是选择所有带有云/类型的行'foo' 现在很简单:

df.loc[df[("clouds", "type", None)] == 'foo']

或选择所有带有foobar 云/类型的行:

df.loc[df[("clouds", "type", None)].isin(['foo', 'bar'])]

如果你使用元组,你将不得不使用类似的东西

df.loc[[any(kind in item for kind in ('foo', 'bar')) 
for item in df[("clouds", "type", None)]]]

请注意,这会更长且更难阅读,而且速度也更慢。

使用多行的一个缺点是它会创建重复的数据,这可能需要更多的内存使用。可能有解决这个问题的方法,例如使用多个表(并且只在需要时加入它们),但对此的讨论将超出这个问题的范围。

所以综上所述,一般来说,使用tidy data ,使用多行,并保持您的 DataFrame dtypes 简单——尽可能使用整数、 float ,必要时使用“字符串”。尽量避免使用元组、列表或 NumPy 数组作为 DataFrame 值。

关于python - pandas loc 函数在写入和读取时引用不同的行 -> ValueError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53262460/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com