【问题标题】:Replace nan cells with lists in Pandas dataframe用 Pandas 数据框中的列表替换 nan 单元格
【发布时间】:2021-09-16 16:33:34
【问题描述】:

我有以下 Pandas 数据框:

index title Open Close
2009-02-13 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 7933.000000 7850.410156
2009-02-14 [613, 6294, 19, 251, 1463, 0, 0, 0, 0, 0, 0, 0... NaN NaN
2009-02-17 NaN 7845.629883 7552.600098
2009-02-18 NaN 7546.350098 7555.629883
2009-02-19 NaN 7555.229980 7465.950195
... ... ... ...
2020-06-07 [29, 68, 245, 3496, 62, 32, 20, 9, 11, 141, 32... NaN NaN
2020-06-08 [898, 30, 22, 1739, 47, 733, 8, 1182, 0, 0, 0,... 27232.929688 27572.439453

其中标题列是新闻标题的索引标记。我不能丢弃 NaN 行,因为它们与以后的处理相关。相反,我想用与非 NaN 单元格大小相同的零列表替换 NaN 值。

我创建了一个零列表:

max_wid = dataframe["title"].map(lambda x: len(x)).max()
zeros = np.zeros(max_wid, dtype=int).tolist()

我设法将第一行的列表分配为.at,但手动替换所有行是不可行的,尽管这是我在网上找到的唯一提示。

我尝试过使用.loc[dataframe.title.isnull(), "title"] = zeros,但它会返回 ValueError: cannot set using a multi-index selection indexer with a different length than the value

我曾想过使用 itertuples,但它不允许设置属性并且不鼓励使用 iterrows。

非常感谢任何帮助。

编辑

通过这样做,我发现了一个低效且不优雅的解决方案:
zeros = np.zeros(max_wid, dtype=int).tolist()
dataframe["isna"] = dataframe.title.isna()
check = dataframe["isna"].values
title = dataframe["title"].values
test = np.empty((dataframe.shape[0]), dtype=object)

for i,v in enumerate(test):
  if check[i] == True:
    test[i] = zeros
  else:
    test[i] = title[i]

dataframe["title"] = test.tolist()
dataframe.drop("isna", axis=1, inplace=True)

如果有人能提出更优化的解决方案,我仍然会非常感激!

【问题讨论】:

  • 看看fillna方法
  • Ciao Nicolò 并欢迎您。如果您可以查看how-to-ask,然后尝试生成mcve,那就太好了。
  • @PauloMarques 我也已经尝试过,但不幸的是 fillna 的值不能是列表。
  • 你怎么能申请max_wid = dataframe["title"].map(lambda x: len(x)).max()却没有得到TypeError: object of type 'float' has no len()

标签: python pandas dataframe numpy


【解决方案1】:

试试:

mask = df.title.notna()

max_wid = df.loc[mask, "title"].str.len().max()
zeros = np.zeros(max_wid, dtype=int).tolist()

df.loc[~mask, "title"] = [zeros]
print(df)

打印:

        index            title
0  2009-02-13        [1, 0, 0]
1  2009-02-14  [613, 6294, 19]
2  2009-02-15        [0, 0, 0]
3  2009-02-16        [0, 0, 0]

df 已使用:

        index            title
0  2009-02-13        [1, 0, 0]
1  2009-02-14  [613, 6294, 19]
2  2009-02-15              NaN
3  2009-02-16              NaN

【讨论】:

  • 嗨,我尝试了你的解决方案,但是当我打电话给df.loc[~mask, "title"] = [zeros]...时,我得到了与问题中相同的 ValueError ...
【解决方案2】:

这里是解决方案:只需在 string(list) 上使用 fillna 而不是原始的 list 并使用 apt 将 str(list) 解析为 list 以使其在 df['title'] 中的所有行都具有相同的类型排。解决方案是完全矢量化的,所以它必须足够快

你是对的,fillna 不适用于list 类型,但你总是可以欺骗它:)。

import pandas as pd
import ast

data = {"index":{"0": "2009-02-13",
                 "1": "2009-02-14",
                 "2": "2009-02-15"
                },
        "title": {"0": [1, 0, 0],
                 "1": [613, 6294, 19]},
        "Open": {"0": 7893,
                 "2": 7845},
        "Close": {"0": 7850,
                  "2": 7855,}
       }

df = pd.DataFrame(data)

mask_isna = df['title'].isna()

max_wid = df.loc[~mask_isna, "title"].str.len().max()
zeros = np.zeros(max_wid, dtype=int).tolist()

df['title'] = df['title'].fillna(str(zeros))
df.loc[mask_isna, 'title'] = df.loc[mask_isna, 'title'].apply(ast.literal_eval)

df 
index title Open Close
0   2009-02-13  [1, 0, 0]   7893.0  7850.0
1   2009-02-14  [613, 6294, 19]     NaN     NaN
2   2009-02-15  [0, 0, 0]   7845.0  7855.0

祝你有美好的一天

【讨论】:

    【解决方案3】:

    我尝试过使用.loc[dataframe.title.isnull(), "title"] = zeros,但它会返回 ValueError: cannot set using a multi-index selection indexer with a different length than the value

    您可以在辅助系列的帮助下完成此方法:

    dataframe.loc[dataframe.title.isnull(), "title"] = pd.Series((zeros,)*dataframe.shape[0], dataframe.index)
    

    【讨论】:

      猜你喜欢
      • 2016-10-16
      • 2018-11-08
      • 2021-11-20
      • 2012-10-29
      • 2022-10-05
      • 2018-08-13
      • 2021-11-24
      相关资源
      最近更新 更多