【问题标题】:Overwrite data in dataframe based on another column根据另一列覆盖数据框中的数据
【发布时间】:2019-12-01 01:44:53
【问题描述】:

假设我有一个包含两列的 csv 文件,一列包含数据(数字),另一列包含格式为“193011”的日期。

我有一个脚本/进程,它以[data, date] 的形式生成新数据。我想要执行以下操作的代码。

如果date 尚未出现在 CSV 中,则应将新数据附加到 CSV 的末尾。这很简单,我知道该怎么做。

如果 date 确实出现在 csv 中,那么我想知道(我已经知道如何执行此操作)并且我想覆盖 csv 中包含该日期的行中的数据。最后一部分我不知道该怎么做。

到目前为止,我只使用 csv 包,但我意识到这对 Pandas 可能很有帮助。对有和没有熊猫的答案开放。

另外,我知道一种可行的方法是在每次添加数据时重写 csv,特别处理与 date 的新值具有相同值的任何行,但这看起来不像对我来说很好的解决方案。

编辑 1

这是数据。基本上我在某个日期做了一个实验,实验将数据输出到一个名为 TEK####.csv 的文件中。记录数据文件的名称和日期。然后处理数据文件以输出finesse_meanfinesse_err 类别中的数值。由于各种原因,数据将被重新处理,重新处理的结果应该是覆盖旧数据或附加到完整的数据集。

mirror_1,mirror_2,finesse_mean,finesse_err,cav_length (mm),date,filename,notes,uid
1,4,12784,None,10,191001,TEK0000.csv,,191001TEK0000.csv
1,4,10058,None,10,191001,TEK0001.csv,,191001TEK0001.csv
1,4,21288,None,8,19`1001,TEK0003.csv,,191001TEK0003.csv
1,4,25843,None,7,191001,TEK0002.csv,,191001TEK0002.csv
5,13,43297,579,3.6,191015,TEK0000.csv,,191015TEK0000.csv
14,15,54531,650,4.75,191022,TEK0000.csv,,191022TEK0000.csv
14,15,80444,542,8.45,191022,TEK0001.csv,,191022TEK0001.csv
14,15,43899,61,8.45,191022,TEK0002.csv,,191022TEK0002.csv
14,15,73906,220,8.45,191022,TEK0003.csv,,191022TEK0003.csv
14,15,83946,306,6,191024,TEK0001.csv,,191024TEK0001.csv
14,15,73607,605,7.85,191024,TEK0002.csv,,191024TEK0002.csv
14,15,84402,611,6,191024,TEK0003.csv,,191024TEK0003.csv
13,15,49706,515,6.26,191029,TEK0000.csv,,191029TEK0000.csv
13,15,65547,403,6.26,191029,TEK0001.csv,,191029TEK0001.csv
13,15,63117,306,6.26,191029,TEK0002.csv,,191029TEK0002.csv
14,15,81584,410,6.14,191101,TEK0000.csv,,191101TEK0000.csv
14,16,19782,269,4.85,191101,TEK0001.csv,,191101TEK0001.csv
14,16,18348,130,5.2,191101,TEK0002.csv,,191101TEK0002.csv
14,15,17038,97,12.75,191104,TEK0000.csv,,191104TEK0000.csv
14,15,16620,43,16.8,191104,TEK0001.csv,,191104TEK0001.csv
14,15,13646,49,18.23,191104,TEK0002.csv,,191104TEK0002.csv
3,15,83146,345,4.15,191107,TEK0000.csv,,191107TEK0000.csv
3,15,69347,477,12,191107,TEK0001.csv,,191107TEK0001.csv
3,15,68372,506,13.75,191107,TEK0002.csv,,191107TEK0002.csv
3,15,67950,582,14.4,191107,TEK0003.csv,,191107TEK0003.csv
3,15,66644,564,15,191107,TEK0004.csv,,191107TEK0004.csv
3,9,22883,197,5.5,191108,TEK0000.csv,,191108TEK0000.csv
3,9,21544,274,8.35,191108,TEK0001.csv,,191108TEK0001.csv
1,9,11474,159,7,191108,TEK0002.csv,,191108TEK0002.csv
3,9,21163,413,7.25,191111,TEK0000.csv,,191111TEK0000.csv
1,8,16949,107,4,191115,TEK0000.csv,,191115TEK0000.csv
1,8,9711,77,9,191115,TEK0001.csv,,191115TEK0001.csv
27,28,44092,481,20,191115,TEK0002.csv,,191115TEK0002.csv
27,28,39812,351,20,191115,TEK0003.csv,,191115TEK0003.csv
27,28,69046,722,20,191115,TEK0004.csv,After Cleaning back mirror,191115TEK0004.csv
27,28,82591,291,20,191115,TEK0005.csv,After Cleaning front mirror,191115TEK0005.csv
27,28,97631,205,12,191119,TEK0004.csv,,191119TEK0004.csv
27,28,99560,408,11,191120,TEK0000.csv,,191120TEK0000.csv
27,28,98735,275,11,191120,TEK0001.csv,,191120TEK0001.csv
27,28,98141,184,11,191120,TEK0002.csv,,191120TEK0002.csv
27,28,103222,222,11,191120,TEK0003.csv,,191120TEK0003.csv
27,28,96684,463,11,191120,TEK0004.csv,,191120TEK0004.csv
27,28,102335,313,11,191120,TEK0005.csv,,191120TEK0005.csv
27,28,102698,311,11,191120,TEK0006.csv,,191120TEK0006.csv
1,8,14469,69,8,191121,TEK0000.csv,,191121TEK0000.csv
1,8,16286,128,5,191121,TEK0001.csv,,191121TEK0001.csv
1,8,16143,64,5,191121,TEK0004.csv,,191121TEK0004.csv
1,7,14272,76,4,191121,TEK0006.csv,,191121TEK0006.csv
1,7,12275,80,4,191121,TEK0007.csv,,191121TEK0007.csv
3,9,13582,61,4.8,191121,TEK0008.csv,,191121TEK0008.csv
14,15,30502,174,5,191122,TEK0000.csv,,191122TEK0000.csv
14,15,44951,152,5,191122,TEK0001.csv,,191122TEK0001.csv
14,15,56137,111,6.7,191122,TEK0002.csv,,191122TEK0002.csv
3,9,14177,55,7,191122,TEK0003.csv,,191122TEK0003.csv
27,28,103871,160,7.75,191122,TEK0004.csv,,191122TEK0004.csv
28,2,54449,1069,3,191122,TEK0005.csv,,191122TEK0005.csv
3,28,79357,653,5.00,191126,TEK0000.csv,,191126TEK0000.csv
9,28,10887,55,4.50,191126,TEK0001.csv,,191126TEK0001.csv
9,28,11435,45,4.50,191126,TEK0002.csv,,191126TEK0002.csv
9,28,21184,70,2.40,191126,TEK0003.csv,,191126TEK0003.csv
3,9,14586,181,4.40,191126,TEK0005.csv,,191126TEK0005.csv
3,9,19954,127,9.80,191126,TEK0006.csv,,191126TEK0006.csv

我的代码能够完成我现在正在寻找的工作,我很快就会在这里发布。

假设我有一个新的数据位:

3, 28, 21352, 122, 7.5, 191127, TEK0001,,191127TEK0001.csv

或旧的修改后的表格数据

3,9,19954,127,9.80,191126,TEK0006.csv,,191126TEK0006.csv

【问题讨论】:

  • 你试过什么?你能分享一些数据吗?我认为重写整个文件是最简单的解决方案,应该不会造成任何问题。
  • @AlexanderCécile 嗯,我想我对这种方法有所保留,因为它似乎效率低下。在我的情况下,文件非常小,因此不会出现性能问题。我想我担心更大的文件。但我想即使对于较大的文件,确定日期是否唯一的步骤无论如何都需要读取大文件的每一行,所以我写的内容不会太多。我将整理一些文件重写版本的代码并将其发布在这里,看看是否有人可以提出改进/替代方法。
  • 我完全可以理解您为什么想要找到更好的选择,我最近也有同样的问题。我还在漫不经心地寻找解决方案,更多的是为了学习。正如您自己所说,加载所有数据通常是必要的,即使不是这样,您也会浪费更多的时间来读取文件,以避免写一些东西。
  • 如果你能分享你的数据,我也可以试着写点东西。
  • @AlexanderCécile 好的,我已经发布了数据。我会尽快发布我的代码 sn-p。

标签: python python-3.x pandas csv dataframe


【解决方案1】:

您可以执行以下操作

1) 使用文件的第一条记录创建一个 Pandas 数据框(比如“df”) “日期”作为索引,文件的“数据”作为一列 2)然后逐条读取文件记录,循环遍历下面的逻辑

如果 df.index 中的“日期”:

df = df.drop('date')
df.loc['date'] = data

其他

df.loc['date'] = 数据

3) 最后将数据从 DataFrame 导出到文件

如果您需要有关如何创建数据框或导入或导出文件的指导,请告诉我。我可以更新帖子

【讨论】:

    【解决方案2】:

    这是我编写的似乎可以完成这项工作的代码。在这段代码中,我创建了一个名称以_temp 为后缀的文件版本,并将原始文件的文件内容逐行复制到新文件中。如果其中一行与当前范围的同一数据集重复,则输入新数据,否则仅从旧文件中复制先前的数据。最后删除旧文件并将新文件重命名为旧名称。即使我将 csv_reader 和 csv_writer 都指向同一个文件,该脚本似乎也能正常工作,但根据我读过的内容,这听起来可能是灾难的根源,新文件 + 重命名感觉像是更好的做法

    import csv
    import os
    from pathlib import Path
    
    def csv_write_overwrite(save_file, data_dict, uid_field='uid'):
        temp_file = Path(str(save_file).strip('.csv') + '_temp.csv')
        new_data_uid = data_dict[uid_field]
        data_saved = False
        with open(save_file, 'r', newline='') as read_file:
            csv_reader = csv.DictReader(read_file)
            with open(temp_file, 'w', newline='') as write_file:
                csv_writer = csv.DictWriter(write_file, fieldnames=data_dict.keys())
                csv_writer.writeheader()
                for line in csv_reader:
                    if line['uid'] != new_data_uid:
                        csv_writer.writerow(line)
                    elif line['uid'] == new_data_uid:
                        csv_writer.writerow(data_dict)
                        data_saved = True
                if not data_saved:
                    csv_writer.writerow(data_dict)
        os.remove(save_file)
        os.rename(temp_file, save_file)
    

    编辑:

    我已通过删除特定于我的特定数据结构的详细信息来更新代码。现在只需要一个 CSV 和数据结构,其中包括一些可以使用 uid_field 的字段。

    这是另一个更通用的代码版本,您可以传入自定义的 duplicate_checking 函数,而不是检查特定的 uid_field 以确定新数据是否重复。

    def csv_write_overwrite(save_file, data_dict, 
                            is_duplicate=lambda x, y: x['uid'] == y['uid']):
        temp_file = Path(str(save_file).strip('.csv') + '_temp.csv')
        data_saved = False
        with open(save_file, 'r', newline='') as read_file:
            csv_reader = csv.DictReader(read_file)
            with open(temp_file, 'w', newline='') as write_file:
                csv_writer = csv.DictWriter(write_file, fieldnames=data_dict.keys())
                csv_writer.writeheader()
                for line in csv_reader:
                    if not is_duplicate(line, data_dict):
                        csv_writer.writerow(line)
                    elif is_duplicate(line, data_dict):
                        csv_writer.writerow(data_dict)
                        data_saved = True
                if not data_saved:
                    csv_writer.writerow(data_dict)
        os.remove(save_file)
        os.rename(temp_file, save_file)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-18
      • 2018-11-12
      • 2016-02-14
      • 2019-11-23
      • 2021-06-11
      • 1970-01-01
      相关资源
      最近更新 更多