在Elasticsearch中索引带有空值但没有NaN值的Pandas数据框。

3

我正在将pandas数据帧中的数据编入elasticsearch索引。

我已经为一些es字段设置了null_value,但并非所有字段都是这样。

如何删除那些没有null_value的列,同时保留那些有null_value的列(将其值设置为None)?

es映射:

    "properties": {
        "sa_start_date": {"type": "date", "null_value": "1970-01-01T00:00:00+00:00"},
        "location_name": {"type": "text"},

代码:

cols_with_null_value = ['sa_start_date']
orig = [{
    'meter_id': 'M1',
    'sa_start_date': '',
    'location_name': ''
},{
    'meter_id': 'M1',
    'sa_start_date': '',
    'location_name': 'a'
}]
df = pd.DataFrame.from_dict(orig)

df['sa_start_date'] = df['sa_start_date'].apply(pd.to_datetime, utc=True, errors='coerce')
df.replace({'': np.nan}, inplace=True)

df:
   meter_id sa_start_date location_name
0       M1           NaT           NaN
1       M1           NaT             a

Elasticsearch索引所需的字典:

{"meter_id": M1, "sa_start_date": None}
{"meter_id": M1, "sa_start_date": None, "location_name": "a"}

请注意,带有NaN的location_name单元格未被索引,但带有NaT的sa_start_date单元格是被索引的。

我尝试了许多方法,每个方法都比上一个更荒谬;没有值得展示的东西。

欢迎各位提出任何想法!

我尝试了这个方法,但Nones和NaNs一起被删除了...

df[null_value_cols] = df[null_value_cols].replace({np.nan: None})
df:
   meter_id sa_start_date location_name
0       M1          None           NaN
1       M1          None             a
for row in df.iterrows():
    ser = row[1]
    ser.dropna(inplace=True)

    lc = {k: v for k, v in dict(row[1]).items()}

lc: {'meter_id': 'M1'}
lc: {'meter_id': 'M1', 'location_name': 'a'}
1个回答

6

不要在这里使用.dropna()。它会删除整行或整列;你只想保留除了空位置名称之外的所有内容。

你可以按照以下方式实现:

df.replace({'': None}, inplace=True) # replace with None instead of np.nan

for idx,row in df.iterrows(): 
    lc = {k:v for k,v in row.items() if not (k == 'location_name' and v is None)} 
    print(lc) 

结果:

{'meter_id': 'M1', 'sa_start_date': None}
{'meter_id': 'M1', 'sa_start_date': None, 'location_name': 'a'}

将NaN替换为None的问题在于数据框中的所有数据类型都将变为“object”。有什么解决办法吗? - Chiel
1
@Chiel:这会引起什么下游问题?我问这个是因为任何可能的解决方案都可能取决于您想对DataFrame进行什么其他操作。 - mechanical_meat
我有一个数据框,其中包含各种类型,包括int64、float64和datetime64s。每当我使用df = df.replace({np.nan: None})时,它可以正确地将NaN、NaT和NA替换为None。但是,数据框中的所有不同数据类型都会变成对象。此外,它通过eland.pandas_to_eland()将所有这些对象发送到Elastic,但由于数据框中的所有列都是对象类型,因此Elastic中的所有内容都变成了关键字。现在,我正在使用pandas_to_eland()中的es_type_overrides参数来覆盖类型。我想知道是否有更简洁的解决方案。 - Chiel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接