用嵌套的dict键值对创建包含项的列表

时间:2018-10-06 10:44:34

标签: python python-3.x pandas list dictionary

我想创建一个新列表,其中包含来自大型嵌套字典的项目。

这是嵌套字典的一个片段:

AcceptedAnswersPython_combined.json

{
  "items": [
    {
      "answers": [
        {
          "creation_date": 1533083368,
          "is_accepted": false
        },
        {
          "creation_date": 1533083567,
          "is_accepted": false
        },
        {
          "creation_date": 1533083754,
          "is_accepted": true
        },
        {
          "creation_date": 1533084669,
          "is_accepted": false
        },
        {
          "creation_date": 1533089107,
          "is_accepted": false
        }
      ],
      "creation_date": 1533083248,
      "tags": [
        "python",
        "pandas",
        "dataframe"
      ]
    },
    {
      "answers": [
        {
          "creation_date": 1533084137,
          "is_accepted": true
        }
      ],
      "creation_date": 1533083367,
      "tags": [
        "python",
        "binary-search-tree"
      ]
    }
  ]
} 

新列表应包含每个项目的creation_date,次数应与answers列表中的字典次数相同。 因此,如果新列表上方的代码段看起来像这样:

question_date_per_answer = [[1533083248, 1533083248, 1533083248 , 1533083248, 1533083248], [1533083367]]

我需要这个新列表的原因是,我想确定每个answers creation_date及其相关问题creation_date(每个{{1}内都有)之间的区别} dict)。

此新列表在pandas Dataframe中应如下所示:

items

我可以像这样遍历所有问题:

     question creation date answer creation date  
0          1533083248             1533083368               
1          1533083248             1533083567               
2          1533083248             1533083754                
3          1533083248             1533084669               
4          1533083248             1533089107               
5          1533083367             1533084137

但这给我留下了一个列表,该列表不等于items = json.load(open('AcceptedAnswersPython_combined.json'))['items'] question_creation_date = [item['creation_date'] for item in items] answers的数量。

我对此一无所知。
那么,如何创建这样一个列表,其中问题创建日期的数量等于答案创建日期的数量? (例如creation_date

谢谢。

2 个答案:

答案 0 :(得分:0)

您需要遍历item [“ answers”],然后为oreder中的每个答案获取creation_date以获取答案创建日期。

my_json = """{
"items": [
    {
    "answers": [
        {
        "creation_date": 1533083368,
        "is_accepted": false
        },
        {
        "creation_date": 1533083567,
        "is_accepted": false
        },
        {
        "creation_date": 1533083754,
        "is_accepted": true
        },
        {
        "creation_date": 1533084669,
        "is_accepted": false
        },
        {
        "creation_date": 1533089107,
        "is_accepted": false
        }
    ],
    "creation_date": 1533083248,
    "tags": [
        "python",
        "pandas",
        "dataframe"
    ]
    },
    {
    "answers": [
        {
        "creation_date": 1533084137,
        "is_accepted": true
        }
    ],
    "creation_date": 1533083367,
    "tags": [
        "python",
        "binary-search-tree"
    ]
    }
]
}"""

import json

data = json.loads(my_json)
dates = [(question["creation_date"], answer["creation_date"])
         for question in data["items"] for answer in question["answers"]]
print(dates)

答案 1 :(得分:0)

您仍然可以使用列表。
让我们尝试从您已经拥有的列表中制作一个数据框-

l = [[1533083248, 1533083248, 1533083248 , 1533083248, 1533083248], [1533083367]]
df = pd.DataFrame(l)

不幸的是,您得到以下信息-

0   1   2   3   4
0   1533083248  1.533083e+09    1.533083e+09    1.533083e+09    1.533083e+09
1   1533083367  NaN     NaN     NaN     NaN

所以我们需要转置它。为此,请执行以下操作-

from itertools import zip_longest
k = list(list(zip_longest(*l))) #Unless the list will be truncated to the length of shortest list.
df = pd.DataFrame(k)

输出-

0   1
0   1533083248  1.533083e+09
1   1533083248  NaN
2   1533083248  NaN
3   1533083248  NaN
4   1533083248  NaN

现在,我们将通过前一个值将NaN向前填充- df.fillna(method='ffill')
整个代码段-

from itertools import zip_longest
l=[1533083248, 1533083248, 1533083248 , 1533083248, 1533083248], [1533083367]
k=list(list(zip_longest(*l)))
df = pd.DataFrame(k)
df.fillna(method='ffill')

Voila-

    0   1
0   1533083248  1.533083e+09
1   1533083248  1.533083e+09
2   1533083248  1.533083e+09
3   1533083248  1.533083e+09
4   1533083248  1.533083e+09