我将使用以下
DataFrame
(可从以下网址下载CSV
here
):
Q1 Unnamed: 2 Unnamed: 3 Q2 Unnamed: 5 Unnamed: 6 Q3 Unnamed: 7 Unnamed: 8
0 A1-A A1-B A1-C A2-A A2-B A2-C A3-A A4-B A3-C
1 A1-A NaN NaN NaN A2-B NaN NaN NaN A3-C
2 NaN A1-B NaN A2-A NaN NaN NaN A4-B NaN
3 NaN NaN A1-C NaN A2-B NaN A3-A NaN NaN
4 NaN A1-B NaN NaN NaN A2-C NaN NaN A3-C
5 A1-A NaN NaN NaN A2-B NaN A3-A NaN NaN
关键假设:
-
名称不以开头的每列
Unnamed
实际上是一个问题的标题
-
问题标题之间的列表示列间隔左端问题的选项
解决方案概述:
-
查找每个问题开始和结束的索引
-
将每个问题展平到一列(
pd.Series
)
-
将问题列重新合并在一起
实施(第1部分):
indices = [i for i, c in enumerate(df.columns) if not c.startswith('Unnamed')]
questions = [c for c in df.columns if not c.startswith('Unnamed')]
slices = [slice(i, j) for i, j in zip(indices, indices[1:] + [None])]
您可以看到,对下面这样的切片进行迭代,可以得到一个
数据帧
每个问题对应:
for q in slices:
print(df.iloc[:, q]) # Use `display` if using Jupyter
实施(第2-3部分):
def parse_response(s):
try:
return s[~s.isnull()][0]
except IndexError:
return np.nan
data = [df.iloc[:, q].apply(parse_response, axis=1)[1:] for q in slices]
df = pd.concat(data, axis=1)
df.columns = questions
输出:
Q1 Q2 Q3
1 A1-A A2-B A3-C
2 A1-B A2-A A4-B
3 A1-C A2-B A3-A
4 A1-B A2-C A3-C
5 A1-A A2-B A3-A