【问题标题】:How to merge multiple CSV files with different languages into one CSV file?如何将多个不同语言的 CSV 文件合并为一个 CSV 文件?
【发布时间】:2021-03-13 07:55:33
【问题描述】:

我有很多 CSV 文件,我想将它们合并为一个 CSV 文件。问题是 CSV 文件包含不同语言的数据,如俄语、英语、克罗地亚语、西班牙语等。一些 CSV 文件甚至有多种语言编写的数据。

当我打开 CSV 文件时,数据看起来非常好,用他们的语言正确编写,我想用他们的语言读取所有 CSV 文件,并将它们原样写入一个大的 CSV 文件。

我使用的代码是这样的:

directory_path = os.getcwd()
all_files=glob.glob(os.path.join(directory_path,"DR_BigData_*.csv"))
print(all_files)
merge_file='data_5.csv'
df_from_each_file=(pd.read_csv(f,encoding='latin1') for f in all_files)
df_merged=pd.concat(df_from_each_file,ignore_index=True)
df_merged.to_csv(merge_file,index=False)

如果我使用“encoding='latin1'”,它会成功地将所有 CSV 文件写入一个文件,但正如您可能猜到的那样,这些字符非常混乱。 下面以部分输出为例:

我也尝试使用 encoding='latin1' 将它们写入 .xlsx,但我仍然遇到同样的问题。除了这些,我尝试了许多不同的编码,但这些都给了我解码错误。

【问题讨论】:

  • 你能不能使用一些特殊字符的 URL 编码,然后将它们正确存储,然后再考虑如何将它们转换回可打印的字符?

标签: python pandas csv encoding


【解决方案1】:

如果我正确理解了您的问题,您可以使用 cat command 轻松合并所有 csv 文件(原样):

cat file1.csv file2.csv file3.csv ... > Merged.csv

【讨论】:

  • 如果所有文件都使用相同的编码,这实际上是可行的,但如果每个文件都有一个标题行,你会得到与数据穿插的标题。
【解决方案2】:

当您将输入编码强制为 Latin-1 时,您基本上会破坏所有实际上不是 Latin-1 的输入文件。例如,在代码页 1251 中包含文本 привет 的俄语文本文件将被静默翻译为 ïðèâåò。 (UTF-8 编码中的相同文本将映射到类似的伪造但完全不同的字符串пÑивеÑ。)

可持续的解决方案是,首先,正确识别每个文件的输入编码,然后,其次,选择一个能够正确容纳所有输入编码的输出编码。

我会选择 UTF-8 作为输出,但任何 Unicode 变体在技术上都可以使用。如果您需要将结果传递给或多或少的脑残(cough Microsoft cough Java),也许 UTF-16 对您来说更方便用例。

data = dict()
for file in glob.glob("DR_BigData_*.csv"):
   if 'ru' in file:
      enc = 'cp1251'
   elif 'it' in file:
      enc = 'latin-1'
   # ... add more here
   else:
      raise KeyError("I don't know the encoding for %s" % file)
   data[file] = pd.read_csv(file, encoding=enc)
# ... merge data[] as previously

if 语句实际上只是一个更有用的占位符;如果无法访问您的文件,我不知道您的文件是如何命名的,也不知道使用哪种编码。这简单地假设俄语文件的名称中都包含子字符串“ru”,并且您希望对所有这些文件使用特定的编码。

如果你只有两种编码,其中一种是 UTF-8,这其实很简单;尝试解码为 UTF-8,如果不起作用,则回退到其他编码:

for file in glob.glob("DR_BigData_*.csv"):
    try:
       data[file] = pd.read_csv(file, encoding='utf-8')
    except UnicodeDecodeError:
       data[file] = pd.read_csv(file, encoding='latin-1')

这很可能会起作用,因为不是有效的 UTF-8 文本通常会很快引发 UnicodeDecodeError。编码的设计使第 8 位设置的字节必须遵守非常特定的模式。这是一个有用的功能,不应该让您感到沮丧。没有从文件中获取正确的数据更糟糕。

如果您不知道什么是编码,现在是阅读 Joel Spolsky 的 The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

的好时机

顺便说一句,您的计算机已经知道它所在的目录;你基本上不需要调用os.getcwd(),除非你需要找出当前目录的绝对路径。

【讨论】:

  • 不管怎样,你的屏幕截图中的俄语数据看起来已经是 UTF-8 格式了。如果您所有的输入文件实际上都是 UTF-8,只需使用它而不是 Latin-1;无需其他代码更改。 (这也会破坏您当前导入的西方文本中偶尔出现的重音字符,例如 doppelgänger。)
  • 这部分帮助我解决了我的问题。如您所见,我使用 pandas 进行合并。有了这个解决方案,我给了 csv reader 一个机会。与此类似,我使用了 try/except,因为我不知道“ru”在“if 'ru' in file:”中是什么意思。我有 utf-8 和 latin1 编码,我在一个列表和一个 for 循环中获得了所有 csv 文件名,如果 csv 阅读器无法读取具有 utf-8 编码的 csv 文件,它将尝试使用 latin1 读取它实际工作。太感谢了。 PS:我仍然很好奇如何使用 pandas 解决它。也许我在 csv 阅读器中使用的方法也适用于 pandas。
  • 再一次,“它有效”只是在你没有得到回溯的意义上;如果真正的编码不是 Latin-1,这意味着你现在在输出文件中有垃圾。
  • if 'ru' in file: 是更有用的占位符;如果无法访问您的文件,我不知道要使用哪些编码,甚至不知道它们是如何命名的。您必须知道每个文件使用哪种编码。如果俄语文件的文件名中有“ru”,这将选择那些文件;但可能你想要更具体的东西,这对你的实际文件是正确的。我将更新答案以更详细地解释这一点。
猜你喜欢
  • 2014-05-17
  • 2019-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多