Python Pandas 数据框:如何从数据框中现有的列表创建列?

3
所以,我有一个从CSV文件读取的Pandas数据帧,看起来像这样:
year,month,day,list
2017,09,01,"[('United States of America', 12345), (u'Germany', 54321), (u'Switzerland', 13524), (u'Netherlands', 24135), ... ]
2017,09,02,"[('United States of America', 6789), (u'Germany', 9876), (u'Switzerland', 6879), (u'Netherlands', 7968), ... ]

第四列中每一行的国家数量不相同。
我希望将第四列中的列表展开,并将数据框转换为以下形式:

year,month,day,country,count
2017,09,01,'United States of America',12345
2017,09,01,'Germany',54321
2017,09,01,'Switzerland',13524
2017,09,01,'Netherlands',24135
...
2017,09,02,'United States of America',6789
2017,09,02,'Germany',9876
2017,09,02,'Switzerland',6879
2017,09,02,'Netherlands',7968
...

我的想法是生成两个独立的列,然后将它们与原始数据框连接起来。可能像这样:

country = df.apply(lambda x:[x['list'][0]]).stack().reset_index(level=1, drop=True)
count  = df.apply(lambda x:[x['list'][1]]).stack().reset_index(level=1, drop=True)
df.drop('list', axis=1).join(country).join(count)

上面的代码肯定不起作用(我只希望它能帮助表达我的想法),而且我也不知道如何扩展日期列。
非常感谢任何帮助或建议。

3个回答

0

可能最简单的解决方法是迭代包含在数据框中的元组并创建一个新的。您可以使用两个嵌套的for循环来实现。

df_new = []
for i in df.itertuples():
    for l in i.list:
        df_new.append([i.year, i.month, i.day, l[0], l[1]])

df_new = pd.DataFrame(df_new, columns=['year', 'month', 'day', 'country', 'count'])

如果列表的第四个字段不是列表而是字符串(数据框示例中的双引号让我有些疑虑),您可以使用 ast 库中的 literal_eval 函数:将列表的字符串表示转换为实际列表对象


非常感谢!我会尝试这种方法,看看是否可行。 - Dan Lwo
你说得对 - 第四列不是一个实际的列表,而是一个字符串,你的方法确实解决了日期的问题。谢谢! - Dan Lwo

0

使用:

import ast
#convert strings to lists of tuples
df['list'] = df['list'].apply(ast.literal_eval)
#create reshaped df from column list
df1 =pd.DataFrame([dict(x) for x in df['list'].values.tolist()]).stack().reset_index(level=1)
df1.columns = ['country','count']
#join to original
df = df.drop('list', 1).join(df1).reset_index(drop=True)
print (df)
   year  month  day                   country  count
0  2017      9    1                   Germany  54321
1  2017      9    1               Netherlands  24135
2  2017      9    1               Switzerland  13524
3  2017      9    1  United States of America  12345
4  2017      9    2                   Germany   9876
5  2017      9    2               Netherlands   7968
6  2017      9    2               Switzerland   6879
7  2017      9    2  United States of America   6789

谢谢!我尝试了一下,这正是我所需要的。 - Dan Lwo
顺便说一下,我发现日期有问题,问题可能出在重新连接部分。如果我找到如何更正它的方法,我会更新的。 - Dan Lwo

0

所以,你需要做的是将一列值的列表转换为多行。其中一个解决方案是创建一个新的数据框,并进行左连接

df = pd.DataFrame({'A':['a','b'],'B':['x','y'],
                   'C':[['a1', 'a2'],['b1', 'b2', 'b3']]})

df
#    A  B               C
# 0  a  x      [[a1, a2]]
# 1  b  y  [[b1, b2, b3]]

dfr=df['C'].apply(lambda k: pd.Series(k)).stack().reset_index(level=1, drop=True).to_frame('C')

dfr
#     C
# 0  a1
# 0  a2
# 1  b1
# 1  b2
# 1  b3

df[['A','B']].join(dfr, how='left')
#    A  B   C
# 0  a  x  a1
# 0  a  x  a2
# 1  b  y  b1
# 1  b  y  b2
# 1  b  y  b3

最后,使用 reset_index()

df[['A','B']].join(dfr, how='left').reset_index(drop=1)
#    A  B   C
# 0  a  x  a1
# 1  a  x  a2
# 2  b  y  b1
# 3  b  y  b2
# 4  b  y  b3

来源:https://dev59.com/bFkS5IYBdhLWcg3wXFvc#39955283


谢谢!我也会尝试这种方法。 - Dan Lwo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接