【问题标题】:Extract information from a string of data in a CSV file从 CSV 文件中的数据字符串中提取信息
【发布时间】:2019-12-03 07:24:38
【问题描述】:

我正在尝试对一些数据进行一些分析,并在解析 csv 文件中的数据时遇到了一些问题。

这是一个单元格中的原始数据:

{"completed": true, "attempts": 1, "item_state": {"1": {"correct": true, "zone": "zone-7"}, "0": {"correct": true, "zone": "zone-2"}, "2": {"correct": true, "zone": "zone-12"}}, "raw_earned": 1.0}

为清晰起见格式化:

{
  "completed": true,
  "attempts": 1,
  "item_state": {
    "1": {
      "correct": true,
      "zone": "zone-7"
    },
    "0": {
      "correct": true,
      "zone": "zone-2"
    },
    "2": {
      "correct": true,
      "zone": "zone-12"
    }
  },
  "raw_earned": 1.0
}

我只想提取每个数字后的区域信息(102)并将结果(zone-7zone-2zone-12)放在单独的列中。如何使用 R 或 Python 做到这一点?

【问题讨论】:

  • 这是 JSON 吗?如果是,有R包可以读取这种数据。
  • 是的,它看起来像 JSON。是的,你可以在 R 和 Python 中做到这一点。两种语言都非常适合这项任务。选择您附近的人(同事、学生等)知道的语言,以便他们可以帮助您。

标签: python r excel


【解决方案1】:

在 Python 中,看起来每个单元格数据都是一个字典,其中还包含字典,即nested dictionaries

如果此单元格的数据被引用为变量 cell_data,那么您可以使用以下命令进入内部“item_state”字典:

cell_data["item_state"]

这将返回

{"1": {"correct": true, "zone": "zone-7"}, "0": {"correct": true, "zone": "zone-2"}, "2": {"correct": true, "zone": "zone-12"}}

然后你可以通过询问“1”字典来更深一层地执行相同的操作:

cell_data["item_state"]["1"]

返回:

{'correct': 'true', 'zone': 'zone-7'}

然后再一次:

cell_data["item_state"]["1"]["zone"]

返回

'zone-7'

因此,要将所有内容组合在一起,您可以通过以下方式获得您想要的:

your_list = list( cell_data["item_state"][i]['zone'] for i in ["1","0","2"] )

返回:

['zone-7', 'zone-2', 'zone-12']

【讨论】:

    【解决方案2】:

    获取item_state 并找到zone 的值,然后将键和值附加到空列表中,最后使用这些列表创建新列

    zone_val = []
    zone_key = []
    
    for k,v in d['item_state'].items():
        zone_val.append(v['zone'])
        zone_key.append(k)
    
    DF[zone_key] = zone_key
    DF[zone_val] = zone_val
    

    【讨论】:

      【解决方案3】:

      它看起来像一个字典,当它作为一个元素存储在 csv 中时,它被存储为一个字符串。在 python 中你可以使用ast.literal_Eval()。它将字符串解析为pythonic 数据类型,如列表、字典等。也可用作数据类型解析器。

      如果您提到的单元格被索引为[i,j]

      import pandas as pd    
      import ast
      df = pd.read_csv(filename)
      a = ast.literal_eval(df.loc[i][j])
      b = pd.io.json.json_normalize(a)
      output = []
      for i in range(df.shape[0]):
        c = ast.literal_eval(df.iloc[i][j])
        temp = pd.DataFrame({'key':c['item_state'].keys(),'zone':[x['zone'] for x in c['item_state'].values()]})
        temp['row_n'] = i
        output.append(temp)
      output2 = pd.concat(temp)
      

      如果[i,j] 是您的单元格, 上面代码中的 a 是您的示例中给出的字典。 b 是一个扁平化字典,包含输出中的所有键、值对。

      其余代码仅提取区域值。 如果您希望将其应用于多个单元格,请使用循环,否则仅使用循环内的内容。 输出是一个列表数据框,每个数据框都有 item_state 键和区域值作为列,还有一个 row_number 用于标识。 output2 是连接的数据帧。

      ast - 抽象语法树

      【讨论】:

      • 你使用的是非标准库,首先你应该注意哪个,然后在你的代码中显示导入作为 df 和 pd 可能不是每个人都清楚
      • 非标准库是什么意思?
      • 我猜 pd 是 pandas 导入,而 df 是 DataFrame,您的答案中没有提到,而且这些不是 python 标准库的一部分
      【解决方案4】:

      在R包rjson中,函数fromJSON使用简单。
      以下任何一种读取 JSON 字符串的方式都将产生相同的结果。

      library("rjson")
      
      x <- '{"completed": true, "attempts": 1, "item_state": {"1": {"correct": true, "zone": "zone-7"}, "0": {"correct": true, "zone": "zone-2"}, "2": {"correct": true, "zone": "zone-12"}}, "raw_earned": 1.0}'
      json <- fromJSON(json_str = x)
      
      # if the string is in a file, say, "so.json"
      #json <- fromJSON(file = "so.json")
      

      json 是类"list" 的对象,用它制作一个数据框。

      result <- data.frame(zone_num = names(json$item_state))
      result <- cbind(result, do.call(rbind.data.frame, json$item_state)[2])
      
      result
      #  zone_num    zone
      #1        1  zone-7
      #0        0  zone-2
      #2        2 zone-12
      

      【讨论】:

        【解决方案5】:

        像这样的东西。由于您没有提供足够的样品,因此未进行测试。

        import csv
        import json
        
        with open('data.csv') as fr:
            rows = list(csv.reader(fr))
        
        for row in rows:
            data = json.loads(row[0])
            new_col_data = [v['zone'] for v in data['item_state'].values()]
            row.append(", ".join(new_col_data)
        
        
        with open('new_data.csv', 'w') as fw:
            writer = csv.writer(fw)
            writer.writerows(rows)
        

        【讨论】:

          【解决方案6】:

          将单元格值转换为 JSON,然后您可以访问任何您想要的元素:

          import csv
          import json
          
          column_index = 0
          state_keys = ['1', '0', '2']
          with open('data.csv') as f:
              reader = csv.reader(f, delimiter=';')
              for row in reader:
                  object = json.loads(row[column_index])
                  state = object['item_state']
                  # Show all values under item_state in order they appear:
                  for key, value in state.items():
                      print(state[key]['zone'])
                  # Show only state_keys defined in variable in order they are defined in a list
                  for key in state_keys:
                      print(state[key]['zone'])
          
          

          【讨论】:

          • 如果数字从1 2 0 变为其他数字怎么办?
          • @MichaelKolber 这只是为了展示访问这种格式化数据中的任何属性是多么容易
          【解决方案7】:

          最初的情况有点不清楚,你显示的看起来像json,但你提到它是在一个csv中。

          假设您有一个 csv,其中各个字段是包含 json 数据的字符串,您可以使用 csv 和 json 包提取区域信息。

          设置一个 for 循环来遍历 csv 的行 (see csv docs for more detail) 然后使用 json 模块从字符串中提取区域。

          import csv
          import json
          
          # to get ss from a csv:
          # my_csv = csv.reader( ... )
          # for row in my_csv:
          #     ss = row[N]
          
          ss = '{"completed": true, "attempts": 1, "item_state": {"1": {"correct": true, "zone": "zone-7"}, "0": {"correct": true, "zone": "zone-2"}, "2": {"correct": true, "zone": "zone-12"}}, "raw_earned": 1.0}'
          
          jj = json.loads(ss)
          
          for vv in jj['item_state'].values():
              print(vv['zone'])
          
          

          【讨论】:

            【解决方案8】:

            在 Python 中,您可以使用 json 库执行以下操作:

            d = json.loads(raw_cell_data)  # Load the data into a Python dict
            results = {}
            for key, value in d['item_state'].items():
                results[key] = value['zone']
            

            然后您可以使用results 打印到 CSV。

            【讨论】:

            • 基本上你重复了我的回答
            • 是的,抱歉,我大约 10 分钟前开始写它,但停下来编辑问题以澄清它。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-01-25
            • 1970-01-01
            • 1970-01-01
            • 2019-03-27
            • 2022-01-13
            • 1970-01-01
            相关资源
            最近更新 更多