Pivot pandas dataframe 从单行到每行一行
Pivot pandas dataframe from single row to one row per item
我最近应用了一个转换来取消嵌套嵌套 json,以便使用一个平面数据集,虽然转换有效,但最终格式不是我正在寻找的格式。它将所有数据压缩成一行,并为列名添加后缀,而不是将每个 id_prop
.
分成不同的列
我的 JSON 格式的数据集要用 Pandas 复制:
import pandas as pd
json = {"id_prop.0":{"0":1},"id_prop.1":{"0":2},"id_prop.2":{"0":3},"prop_number.0":{"0":123},"prop_number.1":{"0":325},"prop_number.2":{"0":754},"prop_value.0":{"0":1},"prop_value.1":{"0":1},"prop_value.2":{"0":1}}
df = pd.DataFrame.from_dict(json, orient='columns')
我的结果:
id_prop.0
id_prop.1
id_prop.2
prop_number.0
prop_number.1
prop_number.2
prop_value.0
prop_value.1
prop_value.2
0
1
2
3
123
325
754
1
1
1
我期望的结果:
id_prop
prop_number
prop_value
0
1
123
1
1
2
325
1
2
3
754
1
有什么方法可以将数据帧转换成我需要的格式,其中每一行代表单个 id_prop
?
的值
尝试
我已经提取了我需要的不带后缀的列的名称:
def extract_cols(columns):
myset = set()
myset_add = myset.add
return [x for x in columns if not (x in myset or myset_add(x))]
cols = extract_cols(df.columns.str.replace("\.[0-9]", "", regex=True))
并且还“垂直化”了我需要使用 stack()
:
的结果
df_stacked = df.stack().reset_index(level=1, drop=True)
但我还没有想出如何组合这些信息。任何帮助将不胜感激。
额外:
如果还有一种方法可以使用 pyspark 来应用它,那就更好了!
您可以将列拆分为多索引,然后将其堆叠:
df.set_axis(
pd.MultiIndex.from_tuples([tuple(i) for i in df.columns.str.split(".")]), axis=1
).stack().droplevel(0)
这里有一个方法:
df = df.T
df.index = pd.MultiIndex.from_arrays([[x[x.find('.')+1:] for x in df.index], [x[:x.find('.')] for x in df.index]])
df = df.unstack()
输入:
id_prop.0 id_prop.1 id_prop.2 prop_number.0 prop_number.1 prop_number.2 prop_value.0 prop_value.1 prop_value.2
0 1 2 3 123 325 754 1 1 1
输出:
id_prop prop_number prop_value
0 1 123 1
1 2 325 1
2 3 754 1
解释:
- 转置以便我们可以使用索引而不是列
- 将每个标签解析为所需的标签(前缀)和结果编号(后缀)由
.
字符分割
- 将 df 的索引更新为具有两个级别的 MultiIndex:结果编号列表和所需标签列表
- 调用
unstack
将 MultiIndex(所需标签)的一个级别旋转为列标题
UPDATE:要处理结果编号是第二个 .
分隔标记并在其右侧附加标记的标签(如 OP 评论中所述),我们可以这样做这个:
import pandas as pd
json = {
"building.0.description.bedrooms":{"0":"qrs"},
"building.1.description.bedrooms":{"0":"tuv"},
"building.2.description.bedrooms":{"0":"xyz"},
"id_prop.0":{"0":1},"id_prop.1":{"0":2},"id_prop.2":{"0":3},
"prop_number.0":{"0":123},"prop_number.1":{"0":325},"prop_number.2":{"0":754},
"prop_value.0":{"0":1},"prop_value.1":{"0":1},"prop_value.2":{"0":1}}
df = pd.DataFrame.from_dict(json, orient='columns')
print(df.to_string())
df = df.T
df.index = pd.MultiIndex.from_arrays([[x.split('.')[1] for x in df.index], ['.'.join(x.split('.')[0:1] + x.split('.')[2:]) for x in df.index]])
df = df.unstack()
df.columns = df.columns.get_level_values(1)
print(df)
输入:
building.0.description.bedrooms building.1.description.bedrooms building.2.description.bedrooms id_prop.0 id_prop.1 id_prop.2 prop_number.0 prop_number.1 prop_number.2 prop_value.0 prop_value.1 prop_value.2
0 qrs tuv xyz 1 2 3 123 325 754 1 1 1
输出:
building.description.bedrooms id_prop prop_number prop_value
0 qrs 1 123 1
1 tuv 2 325 1
2 xyz 3 754 1
我最近应用了一个转换来取消嵌套嵌套 json,以便使用一个平面数据集,虽然转换有效,但最终格式不是我正在寻找的格式。它将所有数据压缩成一行,并为列名添加后缀,而不是将每个 id_prop
.
我的 JSON 格式的数据集要用 Pandas 复制:
import pandas as pd
json = {"id_prop.0":{"0":1},"id_prop.1":{"0":2},"id_prop.2":{"0":3},"prop_number.0":{"0":123},"prop_number.1":{"0":325},"prop_number.2":{"0":754},"prop_value.0":{"0":1},"prop_value.1":{"0":1},"prop_value.2":{"0":1}}
df = pd.DataFrame.from_dict(json, orient='columns')
我的结果:
id_prop.0 | id_prop.1 | id_prop.2 | prop_number.0 | prop_number.1 | prop_number.2 | prop_value.0 | prop_value.1 | prop_value.2 | |
---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 123 | 325 | 754 | 1 | 1 | 1 |
我期望的结果:
id_prop | prop_number | prop_value | |
---|---|---|---|
0 | 1 | 123 | 1 |
1 | 2 | 325 | 1 |
2 | 3 | 754 | 1 |
有什么方法可以将数据帧转换成我需要的格式,其中每一行代表单个 id_prop
?
尝试
我已经提取了我需要的不带后缀的列的名称:
def extract_cols(columns):
myset = set()
myset_add = myset.add
return [x for x in columns if not (x in myset or myset_add(x))]
cols = extract_cols(df.columns.str.replace("\.[0-9]", "", regex=True))
并且还“垂直化”了我需要使用 stack()
:
df_stacked = df.stack().reset_index(level=1, drop=True)
但我还没有想出如何组合这些信息。任何帮助将不胜感激。
额外:
如果还有一种方法可以使用 pyspark 来应用它,那就更好了!
您可以将列拆分为多索引,然后将其堆叠:
df.set_axis(
pd.MultiIndex.from_tuples([tuple(i) for i in df.columns.str.split(".")]), axis=1
).stack().droplevel(0)
这里有一个方法:
df = df.T
df.index = pd.MultiIndex.from_arrays([[x[x.find('.')+1:] for x in df.index], [x[:x.find('.')] for x in df.index]])
df = df.unstack()
输入:
id_prop.0 id_prop.1 id_prop.2 prop_number.0 prop_number.1 prop_number.2 prop_value.0 prop_value.1 prop_value.2
0 1 2 3 123 325 754 1 1 1
输出:
id_prop prop_number prop_value
0 1 123 1
1 2 325 1
2 3 754 1
解释:
- 转置以便我们可以使用索引而不是列
- 将每个标签解析为所需的标签(前缀)和结果编号(后缀)由
.
字符分割 - 将 df 的索引更新为具有两个级别的 MultiIndex:结果编号列表和所需标签列表
- 调用
unstack
将 MultiIndex(所需标签)的一个级别旋转为列标题
UPDATE:要处理结果编号是第二个 .
分隔标记并在其右侧附加标记的标签(如 OP 评论中所述),我们可以这样做这个:
import pandas as pd
json = {
"building.0.description.bedrooms":{"0":"qrs"},
"building.1.description.bedrooms":{"0":"tuv"},
"building.2.description.bedrooms":{"0":"xyz"},
"id_prop.0":{"0":1},"id_prop.1":{"0":2},"id_prop.2":{"0":3},
"prop_number.0":{"0":123},"prop_number.1":{"0":325},"prop_number.2":{"0":754},
"prop_value.0":{"0":1},"prop_value.1":{"0":1},"prop_value.2":{"0":1}}
df = pd.DataFrame.from_dict(json, orient='columns')
print(df.to_string())
df = df.T
df.index = pd.MultiIndex.from_arrays([[x.split('.')[1] for x in df.index], ['.'.join(x.split('.')[0:1] + x.split('.')[2:]) for x in df.index]])
df = df.unstack()
df.columns = df.columns.get_level_values(1)
print(df)
输入:
building.0.description.bedrooms building.1.description.bedrooms building.2.description.bedrooms id_prop.0 id_prop.1 id_prop.2 prop_number.0 prop_number.1 prop_number.2 prop_value.0 prop_value.1 prop_value.2
0 qrs tuv xyz 1 2 3 123 325 754 1 1 1
输出:
building.description.bedrooms id_prop prop_number prop_value
0 qrs 1 123 1
1 tuv 2 325 1
2 xyz 3 754 1