我的目标是能够按列值对 CSV 文件的行进行分组,并执行反向操作。举个例子,希望能够在这两种格式之间来回转换:
uniqueId, groupId, feature_1, feature_2
1, 100, text of 1, 10
2, 100, some text of 2, 20
3, 200, text of 3, 30
4, 200, more text of 4, 40
5, 100, another text of 5, 50
根据groupId分组:
uniqueId, groupId, feature_1, feature_2
1|2|5, 100, text of 1|some text of 2|another text of 5, 10|20|50
3|4, 200, text of 3|more text of 4, 30|40
假定分隔符(此处为 |)不存在于数据中的任何位置。
我正在尝试使用 Pandas 来执行此转换。到目前为止,我的代码可以访问按 groupId 分组的行的单元格,但我不知道如何填充新数据框。
我的方法如何才能完成转换成想要的新df?
将新 df 转换回原始 df 的逆向方法会是什么样子?
如果 R 是这项工作的更好工具,我也乐于接受 R 中的建议。
import pandas as pd
def getGroupedDataFrame(df, groupByField, delimiter):
''' Create a df with the rows grouped on groupByField, values separated by delimiter'''
groupIds = set(df[groupByField])
df_copy = pd.DataFrame(index=groupIds,columns=df.columns)
# iterate over the different groupIds
for groupId in groupIds:
groupRows = df.loc[df[groupByField] == groupId]
# for all rows of the groupId
for index, row in groupRows.iterrows():
# for all columns in the df
for column in df.columns:
print row[column]
# this prints the value the cell
# here append row[column] to its cell in the df_copy row of groupId, separated by delimiter
请您参考如下方法:
要执行分组,您可以在'groupId' 上groupby,然后在每个组内对每一列执行给定分隔符的连接:
def group_delim(grp, delim='|'):
"""Join each columns within a group by the given delimiter."""
return grp.apply(lambda col: delim.join(col))
# Make sure the DataFrame consists of strings, then apply grouping function.
grouped = df.astype(str).groupby('groupId').apply(group_delim)
# Drop the grouped groupId column, and replace it with the index groupId.
grouped = grouped.drop('groupId', axis=1).reset_index()
分组输出:
groupId uniqueId feature_1 feature_2
0 100 1|2|5 text of 1|some text of 2|another text of 5 10|20|50
1 200 3|4 text of 3|more text of 4 30|40
逆过程的想法类似,但由于每一行都是一个独特的组,您可以只使用常规的apply,不需要groupby:
def ungroup_delim(col, delim='|'):
"""Split elements in a column by the given delimiter, stacking columnwise"""
return col.str.split(delim, expand=True).stack()
# Apply the ungrouping function, and forward fill elements that aren't grouped.
ungrouped = grouped.apply(ungroup_delim).ffill()
# Drop the unwieldy altered index for a new one.
ungrouped = ungrouped.reset_index(drop=True)
并且取消分组产生原始数据:
groupId uniqueId feature_1 feature_2
0 100 1 text of 1 10
1 100 2 some text of 2 20
2 100 5 another text of 5 50
3 200 3 text of 3 30
4 200 4 more text of 4 40
要使用不同的分隔符,您只需将 delim 作为参数传递给 apply:
foo.apply(group_delim, delim=';')
作为旁注,通常遍历 DataFrame 非常慢。只要有可能,您就会希望使用矢量化方法,就像我在上面所做的那样。
