首页 > 编程问答 >如何根据现有数据之间的关系填充缺失值

如何根据现有数据之间的关系填充缺失值

时间:2024-07-22 05:14:17浏览次数:8  
标签:python pandas missing-data

问题

如何根据现有的前一行(商品的预测)与另一列中关联的现有值(商品的实际值)之间的关系来填充 pandas 数据框的缺失值。

详细信息| ||我有一个包含 10 列和 40 行的 pandas 数据框。这些列

直至 Date, Actual, time_from_actual_1, time_from_actual_2, time_from_actual_3... time_from_actual_8

列包含商品的实际值,并在 Actual 列中具有每小时时间戳。 Date 列是对同一商品的及时预测。这些每天生成一次,因此预先存在的值为 time_from_actual Index 0 因此,每天有 23 个缺失观测值。 Index 1 输入数据框

我想以非常具体的方式填充这些缺失值。我希望索引 1 到 24 处的“time_from_actual”值在不同时间步长和实际值之间的差异方面遵循与第一列相同的模式。

inptu_df_vscode

输出数据帧

我已经成功做到了这与 a

output_df_vscode

,但我非常希望看到更优雅的方法的建议。下面您将找到包含示例数据、代码和输出的完整尝试。感谢您的任何建议! nested for loop 代码

Code

# imports
import pandas as pd
import numpy as np

# Random seed
np.random.seed(42)

# Sample data
data = {
    'Date': pd.date_range(start='2023-01-01', periods=40, freq='H'),
    'Actual': [100, 99.72, 101.02, 104.06, 103.60, 103.13, 106.29, 107.82, 106.88, 107.97,
               107.04, 106.11, 106.59, 102.77, 99.32, 98.19, 96.17, 96.80, 94.98, 92.15,
               95.09, 94.63, 94.77, 91.92, 90.83, 91.05, 88.75, 89.50, 88.30, 87.72,
               86.51, 90.22, 90.19, 88.08, 89.72, 87.28, 87.70, 83.78, 81.12, 131.52],
    'time_from_actual_1': [97] + [np.nan]*23 + [90] + [np.nan]*15,
    'time_from_actual_2': [99] + [np.nan]*23 + [89] + [np.nan]*15,
    'time_from_actual_3': [98] + [np.nan]*23 + [88] + [np.nan]*15,
    'time_from_actual_4': [97] + [np.nan]*23 + [87] + [np.nan]*15,
    'time_from_actual_5': [96] + [np.nan]*23 + [86] + [np.nan]*15,
    'time_from_actual_6': [95] + [np.nan]*23 + [85] + [np.nan]*15,
    'time_from_actual_7': [94] + [np.nan]*23 + [84] + [np.nan]*15,
    'time_from_actual_8': [93] + [np.nan]*23 + [83] + [np.nan]*15,
}

# dataframe
df = pd.DataFrame(data)

# copy of the dataframe to reference original values only
original_df = df.copy()

# Fill missing values for columns starting with "time_from_actual"
time_cols = [col for col in df.columns if col.startswith('time_from_actual')]

for col in time_cols:
    for i in range(1, len(df)):
        if pd.isnull(df.loc[i, col]):
            j = i
            while j < len(df) and pd.isnull(original_df.loc[j, col]):
                previous_actual = df.loc[j - 1, 'Actual']
                previous_time = df.loc[j - 1, col]
                current_actual = df.loc[j, 'Actual']
                difference = previous_time - previous_actual
                df.loc[j, col] = current_actual + difference
                j += 1

可以通过利用 pandas 的矢量化运算和索引功能来简化此代码。这是一个更优雅的解决方案:

import pandas as pd
import numpy as np

# Sample data (same as yours)
data = {
    'Date': pd.date_range(start='2023-01-01', periods=40, freq='H'),
    'Actual': [100, 99.72, 101.02, 104.06, 103.60, 103.13, 106.29, 107.82, 106.88, 107.97,
               107.04, 106.11, 106.59, 102.77, 99.32, 98.19, 96.17, 96.80, 94.98, 92.15,
               95.09, 94.63, 94.77, 91.92, 90.83, 91.05, 88.75, 89.50, 88.30, 87.72,
               86.51, 90.22, 90.19, 88.08, 89.72, 87.28, 87.70, 83.78, 81.12, 131.52],
    'time_from_actual_1': [97] + [np.nan]*23 + [90] + [np.nan]*15,
    'time_from_actual_2': [99] + [np.nan]*23 + [89] + [np.nan]*15,
    'time_from_actual_3': [98] + [np.nan]*23 + [88] + [np.nan]*15,
    'time_from_actual_4': [97] + [np.nan]*23 + [87] + [np.nan]*15,
    'time_from_actual_5': [96] + [np.nan]*23 + [86] + [np.nan]*15,
    'time_from_actual_6': [95] + [np.nan]*23 + [85] + [np.nan]*15,
    'time_from_actual_7': [94] + [np.nan]*23 + [84] + [np.nan]*15,
    'time_from_actual_8': [93] + [np.nan]*23 + [83] + [np.nan]*15,
}

df = pd.DataFrame(data)

# 获取以"time_from_actual"开头的列名
time_cols = [col for col in df.columns if col.startswith('time_from_actual')]

for col in time_cols:
    # 计算第一个非 NaN 值与其对应“实际”值之间的差值
    difference = df[col].first_valid_index() - df['Actual'].iloc[0]

    # 使用 forward fill 和累积差值来填充 NaN 值
    df[col] = df[col].ffill() + (df['Actual'] - df['Actual'].ffill()).cumsum() + difference

此代码执行以下操作:

  1. 计算差值: 对于每个“time_from_actual”列,它都会识别第一个非 NaN 值,并计算该值与“Actual”列中第一个值的差值。此差值表示该特定时间步长的模式。
  2. 前向填充和累积差值: 它使用 ffill() (前向填充)来填充每个组中的第一个非 NaN 值。然后,它会计算“Actual”列中的更改(使用 diff() )并使用 cumsum() (累积求和)对其进行累积。这将创建一组反映“Actual”列中更改的偏移量。
  3. 应用偏移量: 最后,它会将计算的差值添加到累积偏移量中。这可以确保填充值遵循原始模式,即使“Actual”列中的值有波动。

此方法利用了 pandas 内置函数的矢量化性质,使其比使用循环效率更高。它还更简洁易懂。

标签:python,pandas,missing-data
From: 78776354

相关文章

  • Python + VS Code 调试器:可视化我的程序当前正在执行的源代码中的位置?
    当我使用VSCodePython调试器时:我可以执行我的程序,以便编辑器将我逐行带到源代码中的任何位置(跳转到相关文件/如果尚未打开则将其打开)目前的执行情况是?是的,VSCode的Python调试器可以让你逐行执行代码,并实时显示当前执行的位置。以下是操作方法:1.设置断点:......
  • 在 pandas 中用 NaN 替换空白值(空白)
    我想找到Pandas数据框中包含空格(任意数量)的所有值,并将这些值替换为NaN。有什么想法可以改进吗?基本上我想把这个:ABC2000-01-01-0.532681foo02000-01-021.490752bar12000-01-03-1.387326foo22000-01-040.8147......
  • 如何立即取消使用 Ollama Python 库生成答案的 Asyncio 任务?
    我正在使用Ollama通过OllamaPythonAPI从大型语言模型(LLM)生成答案。我想通过单击停止按钮取消响应生成。问题在于,只有当响应生成已经开始打印时,任务取消才会起作用。如果任务仍在处理并准备打印,则取消不起作用,并且无论如何都会打印响应。更具体地说,即使单击按钮后,此函数......
  • 使用 np.array 索引过滤 Python 列表
    谁能向我解释一下列表self.data如何使用numpy索引数组selec_idx进行索引/过滤?完整的课程可在https://github.com/kaidic/LDAM-DRW/blob/master/imbalance_cifar.pydefgen_imbalanced_data(self,img_num_per_cls):new_data=[]n......
  • 尝试在cmd(python)中安装turtle
    当我在cmd中编写pipinstallturtle后,这条消息出现在我面前。有人知道该怎么办吗?C:\>pipinstallturtleCollectingturtleUsingcachedturtle-0.0.2.tar.gz(11kB)ERROR:Commanderroredoutwithexitstatus1:command:'C:\Users\Bruger\App......
  • Python + Polars:如何有效地“fill_null”仅 DataFrame 的某些列?
    例如,假设我只想fill_null(strategy="zero")DataFrame的数字列。我当前的策略是这样做:final_df=df.select(cs.exclude(cs.numeric()))final_df.with_columns(df.select(cs.numeric()).fill_null(strategy="zero"))是否有替代的、更惯用或更有效的方法来实现我......
  • 如何将 geopandas 数据框与底图重叠?
    我有一个shapefile,我将其读取为geopandas数据框importgeopandasasgpdgdf=gpd.read_file('myfile.shp')gdf.plot()其中gdf.crs<ProjectedCRS:ESRI:54009>Name:World_MollweideAxisInfo[cartesian]:-E[east]:Easting(metre)-......
  • 如何找到 Windows 上 Python 的安装位置?
    我想找出我的Python在Windows上的安装路径。例如:C:\Python25如何找到Python的安装位置?在Windows上查找Python安装位置的方法有很多种:1.使用where命令(推荐方法):打开命令提示符(cmd)。输入以下命令并按回车键:wherepython......
  • Python Pandas:如何解析没有行结尾的 CSV
    如何解析没有行结尾的CSV文件?示例数据sep=;Id;Date;1;1980-02-29;2;1980-03-10;3;;可以使用lineterminator参数指定行终止符来解析没有行尾的CSV文件。在这种情况下,你可以将lineterminator设置为一个空字符串('')。以下是使用......
  • Python 中的 azure.ai.translation.document - 无法使用当前权限访问源文档位置
    我在使用Python中的azure.ai.translation.document库时遇到问题。我已经在Azure中设置了翻译服务以及带有两个容器的Blob存储。我已使用“用户委托密钥”创建了SAS连接。一种用于源(读取/列表),一种用于目标(写入/列表)。例如我尝试运行Python程序,但源b......