python - 通过创建具有唯一键的新数据帧,将非范式数据帧转换为 1NF
问题描述
我不太清楚如何提出这个问题,欢迎提出改进标题的建议。
让我们从我的巨大桌子开始,其中有多个不属于任何正常形式的道具。我用多种语言特定的数据集创建了这个表。
+-----+---------+--------+-----+----------+
| Key | Prop_A | Prob_B | ... | Language |
+-----+---------+--------+-----+----------+
| 1 | Light | Stone | | EN |
| 2 | Medium | Wood | | EN |
| 1 | Leicht | Stein | | DE |
| 3 | Hard | Stone | | EN |
| 2 | Mittel | Holz | | DE |
我会压缩它们并在单独的数据帧中提取冗余信息。所以结果应该是这样的:
Example: with NF
+-----+---------+--------+
| Key | Prop_A | Prob_B |
+-----+---------+--------+
| 1 | LIGHT | STONE |
| 2 | MEDIUM | WOOD |
| 3 | HARD | STONE |
+-----+---------+--------+
大写的值代表离散值的属性表的主键
Example: Prop_A Table
+--------+---------+--------+
| Key | EN | DE |
+--------+---------+--------+
| LIGHT | Light | Leicht |
| MEDIUM | Medium | Mittel |
| HARD | Hard | Hart |
| | | |
+--------+---------+--------+
我的第一个想法是分组Key
,Language
然后将属性(Prob_A,Prob_B)应用于字典。我试过了groupby('key')[['Prob_A', 'Language']].apply(lambda x: x.values.tolist()).to_dict()
。但是我总是失败,因为我从来没有得到靠近我上面桌子的东西。
第二个想法是按两个步骤分组。首先按键分组,然后按语言和属性本身分组。收集列表中的结果。最后一个想法是按键和语言分组并遍历所有行。在循环中,值应该收集在一个集合中,每个属性也包含语言信息。但是我不知道集合的结构应该是什么样子,结果看起来像上面那样。
还阅读了 pandas 文档中关于多索引和分类的一些章节,但它不适合我的用例。在过去,我更多地使用 pandas 来聚合数值而不是数据转换。
我觉得我为我的问题使用了错误的工具(熊猫)。在我的脑海中,这个想法很清楚,但我看不到 pandas 的解决方案。你能给我一些想法如何用熊猫或其他建议解决这个问题吗?
我的演示 DF 看起来像
lst = [["1",'Light', "Stone", "EN"],["2",'Medium', "Wood", "EN"], ["1",'Leicht', "Stein", "DE"],["3",'Hard', "Stone", "EN"],["2",'Mittel', "Holz", "DE"]]
df = pd.DataFrame(lst,columns= ['Key','Prop_A', 'Prob_B','Language'])
columns = ['Prop_A', 'Prob_B']
解决方案
创建一个dictionary
其中 eachkey
是列,内容是每列的属性表,然后只需修改原始数据框。由于字典是根据原始字典创建的,因此不会丢失任何键:
columns = ['Prop_A', 'Prob_B']
dfs = {
col:
df[['Key', col, 'Language']].pivot(
columns='Language', values=col, index='Key')
for col in columns
}
dfs['Prop_A']
# DE EN
# Key
# LIGHT LEICHT LIGHT
# MEDIUM MITTEL MEDIUM
# HARD NaN HARD
df_f = df.query('Language == "EN"')[['Key'] + columns].\
apply(lambda x: x.str.upper() if x.name in columns else x).\
drop_duplicates()
df_f
# Key Prop_A Prob_B
# 0 1 LIGHT STONE
# 1 2 MEDIUM WOOD
# 3 3 HARD STONE
示例中没有Hart
inProp_A
推荐阅读
- angular - *NgIf 异步对象触发 else 部分
- angular - Socket.Io 没有在 Chrome 中触发任何事件
- c - 为什么我的 if 语句函数没有填充我的变量 (C)?
- json - 使用 React 显示来自 API 的数据
- android - 如何在 React Native 中生成用于本地分发的 APK?
- javascript - 使用 Cypress 和 cypress-file-upload 时出现“多部分数据意外结束”
- scala - 用火花将一个大的csv分成多个csv
- axapta - 调用c#库时X++“invalid token”消息(如何正确调用方法)
- go - ElasticSearch:条件总和
- javascript - 使用javascript在图像之间切换