【问题标题】:Reformatting fields as columns, other fields (paired with the fields to become columns in the previous structure) to become fields in the new columns将字段重新格式化为列,其他字段(与字段配对成为先前结构中的列)成为新列中的字段
【发布时间】:2021-02-15 00:49:53
【问题描述】:

我的任务是清理慈善机构设计的移动应用程序中的数据

在一个部分中,用户 Q/A 应用使用会话由一行表示。此部分由重复的问题答案字段对组成,其中一个字段代表所提出的问题,然后它旁边的字段代表相应的答案。每个问题/字段和答案列对一起代表一个带有答案的唯一问题。

起始数据

    answers.0.answer    answers.0.fieldName answers.1.answer    answers.1.fieldName
5   0                    avoidexercise             0.0            vomitflag
6   156                  height                    54.0         weight
7   1                    affectedkneeside           3.0       painlocationknee

我被要求重新格式化该部分,以便每个问题形成一个列,相应的答案是该列中的一个字段

理想的输出

_id                    avoidexercise    enjoyment   fatigue2weeks   height
        

5f27f29c362a380d3f9a9e46    1.0           yes            20.0       120.0
5f27f2ac362a380d3f9a9e4b    0.0           no             40.0       180.0
5f27f4d4362a380d3f9a9e52    1.0           yes            50.0       150.0

我的计划是创建许多数据透视表,从彼此的 Q/A 对列开始,然后连接(外连接)然后内连接以删除重复项

但是,原始数据框包含数字和对象数据类型的混合

因此,似乎只有一些问题/答案列对正在转换为数据透视表。我尝试过使用各种聚合函数

p1 = ur.pivot_table(index=['_id'],columns= ['answers.0.fieldName'],values=['answers.0.answer'],aggfunc=lambda x: ' '.join(x))
p2 = ur.pivot_table(index=['_id'],columns= ['answers.1.fieldName'],values=['answers.1.answer'],aggfunc=lambda x: ' '.join(x))
p3 = ur.pivot_table(index=['_id'],columns= ['answers.2.fieldName'],values=['answers.2.answer'],aggfunc=lambda x: ' '.join(x))
I have also tried another lambda function

p1 = ur.pivot_table(index=['_id'],columns= ['answers.0.fieldName'],values=['answers.0.answer'],aggfunc=lambda x: ' '.join(str(v) for v in x)
The furthest I have got so far is to run pivots with standard mean aggfunc

p1 = ur.pivot_table(index=['_id'],columns=['answers.0.fieldName'],values=['answers.0.answer'])
ps = [p1,p2,p3]
c = pd.concat(ps)

然后尝试删除合并行和列

df = c.sum(axis=1, level=1, skipna=False)

g = df.groupby('_id').agg(np.sum)

这会返回一个形状正确的数据框

但是,它会丢失对象列中的值,我不确定所有数字列的准确性如何

为了克服这个问题,我正在考虑将尽可能多的数据转换为数字

c4 = c.apply(pd.to_numeric, errors='ignore').info()

然后将组合数据透视表数据框拆分为数字和对象类型

nu = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
cndf = c4.select_dtypes(include=nu)
o = ['object', 'bool', 'datetime64', 'category']
codf = c4.select_dtypes(include=o)

并在数字数据帧上运行与上述相同的 .sum 和 groupby 操作

n1 = cndf.sum(axis=1, level=1, skipna=False)
n2 = n1.groupby('_id').agg(np.sum)

但是,这仍然留下了处理对象列的挑战

【问题讨论】:

  • 您好,无法从您提供的图像中复制数据帧。请参考此答案以了解如何在您的问题中包含可重现的熊猫代码:stackoverflow.com/a/20159305/11130170
  • 我明白了,我已经输入了帧 Ishwar
  • 谢谢,我已经发布了答案。看看有没有帮助。

标签: python excel database data-cleaning data-munging


【解决方案1】:

这是获得所需结果的方法:

首先定义你拥有的问答对的数量:

num_answers = 2 #Following your 'Starting data' in the question

然后根据需要使用以下几行获取数据帧:

import pandas as pd
df2 = pd.concat([pd.pivot_table(df1, index=['_id'], columns= ['answers.{}.fieldName'.format(i)], values=['answers.{}.answer'.format(i)]) for i in range(num_answers)], axis = 1).fillna('N/A')
df2.columns = [col[1] for col in df2.columns]

这里df1 被假定为带有起始数据的数据框。

您可能已经注意到,“N/A”出现在特定 ID 没有针对该特定字段记录答案的单元格中。

假设三行的 ID 分别为 [1,2,3],“起始数据”的输出 df2 将如下所示:

      affectedkneeside  avoidexercise   height  painlocationknee    vomitflag   weight
_id                     
0          N/A                0           N/A         N/A              0         N/A
1          N/A               N/A          156         N/A              N/A       54
2           1                N/A          N/A          3               N/A       N/A

【讨论】:

  • 嘿 Ishwar,我真的很喜欢这个但是,不幸的是,原始数据帧有混合数据,所以我收到一个 DataError:当我尝试联系所有 68 对时,没有要聚合的数字类型
  • 我也喜欢你的代码,我可以为你的每一个解决方案付钱吗?
  • 我们如何使用 apply 以某种方式 ur.iloc[:,5:136:2].apply(pd.Series.value_counts, axis=1) 这只是告诉我们天气或用户是否已回答一个问题是否可以对 .valuecounts() 使用不同的方法
  • 这是一个开放的论坛,所以你不需要付费:)!如果对您有帮助,您可以投票并接受答案,那就行了:)
  • 我不确定 .iloc 方法是否可行!
猜你喜欢
  • 1970-01-01
  • 2021-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
  • 2012-11-14
  • 2018-03-31
相关资源
最近更新 更多